From e3b5d7fd7c6d616d87f3c81794e35629b65a7899 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 6 Dec 2019 19:21:26 +0300 Subject: [PATCH] rename if_st to if_statement --- vlib/compiler/expression.v | 2 +- vlib/compiler/{match.v => if_match.v} | 124 +++++++++++++++++++++++++- vlib/compiler/parser.v | 117 +----------------------- 3 files changed, 122 insertions(+), 121 deletions(-) rename vlib/compiler/{match.v => if_match.v} (61%) diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index 0b9b7cb2cb..1d30a30caa 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -743,7 +743,7 @@ fn (p mut Parser) factor() string { return p.assoc() } .key_if { - typ = p.if_st(true, 0) + typ = p.if_statement(true, 0) return typ } .key_match { diff --git a/vlib/compiler/match.v b/vlib/compiler/if_match.v similarity index 61% rename from vlib/compiler/match.v rename to vlib/compiler/if_match.v index 65abd2c7ae..cf982a2e04 100644 --- a/vlib/compiler/match.v +++ b/vlib/compiler/if_match.v @@ -8,14 +8,14 @@ import ( strings ) -// Returns typ if used as expression +// Returns type if used as expression fn (p mut Parser) match_statement(is_expr bool) string { p.check(.key_match) p.fspace() typ, expr := p.tmp_expr() if typ.starts_with('array_') { p.error('arrays cannot be compared') - } + } // is it safe to use p.cgen.insert_before ??? tmp_var := p.get_tmp() p.cgen.insert_before('$typ $tmp_var = $expr;') @@ -37,7 +37,7 @@ fn (p mut Parser) match_statement(is_expr bool) string { p.check(.key_else) if p.tok == .arrow { p.error(warn_match_arrow) - } + } // unwrap match if there is only else if i == 0 { @@ -169,7 +169,7 @@ fn (p mut Parser) match_statement(is_expr bool) string { if p.tok == .arrow { p.error(warn_match_arrow) p.check(.arrow) - } + } // statements are dissallowed (if match is expression) so user cant declare variables there and so on if is_expr { @@ -221,4 +221,120 @@ fn (p mut Parser) switch_statement() { 'https://vlang.io/docs#match') } +fn (p mut Parser) if_statement(is_expr bool, elif_depth int) string { + if is_expr { + //if p.fileis('if_expr') { + //println('IF EXPR') + //} + p.inside_if_expr = true + p.gen('((') + } + else { + p.gen('if (') + } + p.next() + p.fspace() + // `if a := opt() { }` syntax + if p.tok == .name && p.peek() == .decl_assign { + p.check_not_reserved() + option_tmp := p.get_tmp() + var_name := p.lit + p.next() + p.check(.decl_assign) + p.is_var_decl = true + option_type, expr := p.tmp_expr()// := p.bool_expression() + p.is_var_decl = false + typ := option_type[7..] + // Option_User tmp = get_user(1); + // if (tmp.ok) { + // User user = *(User*)tmp.data; + // [statements] + // } + p.cgen.insert_before('$option_type $option_tmp = $expr; ') + p.check(.lcbr) + p.genln(option_tmp + '.ok) {') + p.genln('$typ $var_name = *($typ*) $option_tmp . data;') + p.register_var(Var { + name: var_name + typ: typ + is_mut: false // TODO + //is_alloc: p.is_alloc || typ.starts_with('array_') + //line_nr: p.tokens[ var_token_idx ].line_nr + //token_idx: var_token_idx + }) + p.statements() + p.returns = false + return 'void' + } else { + p.check_types(p.bool_expression(), 'bool') + } + if is_expr { + p.gen(') ? (') + } + else { + p.genln(') {') + } + p.fspace() + p.check(.lcbr) + mut typ := '' + // if { if hack + if p.tok == .key_if && p.inside_if_expr { + typ = p.factor() + p.next() + } + else { + typ = p.statements() + } + if_returns := p.returns + p.returns = false + if p.tok == .key_else { + if !p.inside_if_expr { + p.fgen_nl() + } + p.check(.key_else) + p.fspace() + if p.tok == .key_if { + if is_expr { + p.gen(') : (') + nested := p.if_statement(is_expr, elif_depth + 1) + nested_returns := p.returns + p.returns = if_returns && nested_returns + return nested + } + else { + p.gen(' else ') + nested := p.if_statement(is_expr, 0) + nested_returns := p.returns + p.returns = if_returns && nested_returns + return nested + } + // return '' + } + if is_expr { + p.gen(') : (') + } + else { + p.genln(' else { ') + } + p.check(.lcbr) + // statements() returns the type of the last statement + first_typ := typ + typ = p.statements() + p.inside_if_expr = false + if is_expr { + p.check_types(first_typ, typ) + p.gen(strings.repeat(`)`, 2 * (elif_depth + 1))) + } + else_returns := p.returns + p.returns = if_returns && else_returns + return typ + } + p.inside_if_expr = false + if p.fileis('test_test') { + println('if ret typ="$typ" line=$p.scanner.line_nr') + } + return typ +} + + diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 7aaf5fa46c..681fb8d31a 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -1276,7 +1276,7 @@ fn (p mut Parser) statement(add_semi bool) string { p.comp_time() } .key_if { - p.if_st(false, 0) + p.if_statement(false, 0) } .key_for { p.for_st() @@ -2638,121 +2638,6 @@ fn (p mut Parser) get_tmp_counter() int { } -fn (p mut Parser) if_st(is_expr bool, elif_depth int) string { - if is_expr { - //if p.fileis('if_expr') { - //println('IF EXPR') - //} - p.inside_if_expr = true - p.gen('((') - } - else { - p.gen('if (') - } - p.next() - p.fspace() - // `if a := opt() { }` syntax - if p.tok == .name && p.peek() == .decl_assign { - p.check_not_reserved() - option_tmp := p.get_tmp() - var_name := p.lit - p.next() - p.check(.decl_assign) - p.is_var_decl = true - option_type, expr := p.tmp_expr()// := p.bool_expression() - p.is_var_decl = false - typ := option_type[7..] - // Option_User tmp = get_user(1); - // if (tmp.ok) { - // User user = *(User*)tmp.data; - // [statements] - // } - p.cgen.insert_before('$option_type $option_tmp = $expr; ') - p.check(.lcbr) - p.genln(option_tmp + '.ok) {') - p.genln('$typ $var_name = *($typ*) $option_tmp . data;') - p.register_var(Var { - name: var_name - typ: typ - is_mut: false // TODO - //is_alloc: p.is_alloc || typ.starts_with('array_') - //line_nr: p.tokens[ var_token_idx ].line_nr - //token_idx: var_token_idx - }) - p.statements() - p.returns = false - return 'void' - } else { - p.check_types(p.bool_expression(), 'bool') - } - if is_expr { - p.gen(') ? (') - } - else { - p.genln(') {') - } - p.fspace() - p.check(.lcbr) - mut typ := '' - // if { if hack - if p.tok == .key_if && p.inside_if_expr { - typ = p.factor() - p.next() - } - else { - typ = p.statements() - } - if_returns := p.returns - p.returns = false - if p.tok == .key_else { - if !p.inside_if_expr { - p.fgen_nl() - } - p.check(.key_else) - p.fspace() - if p.tok == .key_if { - if is_expr { - p.gen(') : (') - nested := p.if_st(is_expr, elif_depth + 1) - nested_returns := p.returns - p.returns = if_returns && nested_returns - return nested - } - else { - p.gen(' else ') - nested := p.if_st(is_expr, 0) - nested_returns := p.returns - p.returns = if_returns && nested_returns - return nested - } - // return '' - } - if is_expr { - p.gen(') : (') - } - else { - p.genln(' else { ') - } - p.check(.lcbr) - // statements() returns the type of the last statement - first_typ := typ - typ = p.statements() - p.inside_if_expr = false - if is_expr { - p.check_types(first_typ, typ) - p.gen(strings.repeat(`)`, 2 * (elif_depth + 1))) - } - else_returns := p.returns - p.returns = if_returns && else_returns - return typ - } - p.inside_if_expr = false - if p.fileis('test_test') { - println('if ret typ="$typ" line=$p.scanner.line_nr') - } - return typ -} - fn (p mut Parser) assert_statement() { if p.first_pass() { return