From f724a956b3884e1c0e868cdd1e6d8dcc429e8242 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 29 Nov 2019 22:42:32 +0300 Subject: [PATCH] parser: fix `a & b == c` precedence --- vlib/builtin/int_test.v | 9 +++++++++ vlib/compiler/expression.v | 34 +++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/vlib/builtin/int_test.v b/vlib/builtin/int_test.v index 7f266d35c8..a2f955945f 100644 --- a/vlib/builtin/int_test.v +++ b/vlib/builtin/int_test.v @@ -66,6 +66,15 @@ fn test_str_methods() { assert u64(-1).str() == '18446744073709551615' } +fn test_and() { + c:=[1,2,3,4,5] + assert c[0] & 1 != 0 + assert c[1] & 1 == 0 + assert c[2] & 1 != 0 + assert c[3] & 1 == 0 + assert c[4] & 1 != 0 +} + /* fn test_cmp() { assert 1 ≠ 2 diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index 3a93b4f68e..1f892c6c87 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -32,7 +32,7 @@ fn (p mut Parser) bool_expression() string { p.check_types(p.bterm(), typ) if typ != 'bool' { p.error('logical operators `&&` and `||` require booleans') - } + } } if typ == '' { println('curline:') @@ -162,7 +162,7 @@ fn (p mut Parser) name_expr() string { mut name := p.lit // generic type check - if name in p.cur_fn.dispatch_of.inst.keys() { + if name in p.cur_fn.dispatch_of.inst.keys() { name = p.cur_fn.dispatch_of.inst[name] } @@ -227,7 +227,7 @@ fn (p mut Parser) name_expr() string { !p.table.known_fn(name) && !p.table.known_const(name) && !is_c { name = p.prepend_mod(name) - } + } // re-check if p.known_var_check_new_var(name) { return p.get_var_type(name, ptr, deref_nr) @@ -269,7 +269,7 @@ fn (p mut Parser) name_expr() string { // `if color == .red` is enough // no need in `if color == Color.red` p.warn('`${enum_type.name}.$val` is unnecessary, use `.$val`') - } + } // println('enum val $val') p.gen(mod_gen_name(enum_type.mod) + '__' + enum_type.name + '_' + val)// `color = main__Color_green` p.next() @@ -286,7 +286,7 @@ fn (p mut Parser) name_expr() string { return p.get_const_type(name, ptr) } // TODO: V script? Try os module. - // Function (not method, methods are handled in `.dot()`) + // Function (not method, methods are handled in `.dot()`) mut f := p.table.find_fn_is_script(name, p.v_script) or { // First pass, the function can be defined later. if p.first_pass() { @@ -336,7 +336,7 @@ fn (p mut Parser) name_expr() string { if p.tok == .question { // `files := os.ls('.')?` return p.gen_handle_question_suffix(f, fn_call_ph) - } + } else if !p.is_var_decl && is_or_else { f.typ = p.gen_handle_option_or_else(f.typ, '', fn_call_ph) } @@ -471,16 +471,24 @@ fn (p mut Parser) expression() string { } if is_str && tok_op != .plus { p.error('strings only support `+` operator') - } + } expr_type := p.term() - if (tok_op in [.pipe, .amp, .xor]) && !(is_integer_type(expr_type) && - is_integer_type(typ)) { - p.error('operator ${tok_op.str()} is defined only on integer types') - } + mut open := false + if tok_op in [.pipe, .amp, .xor] { + if !(is_integer_type(expr_type) && is_integer_type(typ)) { + p.error('operator ${tok_op.str()} is defined only on integer types') + } + p.cgen.set_placeholder(ph, '(') + open = true + } p.check_types(expr_type, typ) if (is_str || is_ustr) && tok_op == .plus && !p.is_js { p.gen(')') } + if open { + p.gen(')') + + } // Make sure operators are used with correct types if !p.pref.translated && !is_str && !is_ustr && !is_num { T := p.table.find_type(typ) @@ -546,14 +554,14 @@ fn (p mut Parser) term() string { } continue } - + if is_mod { if !(is_integer_type(expr_type) && is_integer_type(typ)) { p.error('operator `mod` requires integer types') } } else { p.check_types(expr_type, typ) - } + } } return typ }