From 581d836de6bc53a837628db293939fc6ea5375c9 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 11 Apr 2020 21:31:54 +0200 Subject: [PATCH] !in operator --- vlib/v/checker/checker.v | 13 +++++++------ vlib/v/gen/cgen.v | 5 ++++- vlib/v/scanner/scanner.v | 4 ++++ vlib/v/token/token.v | 6 ++++-- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 97d1a9a9e1..55810c1efe 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -198,7 +198,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { return table.void_type } } - if infix_expr.op == .key_in { + if infix_expr.op in [.key_in, .not_in] { if !(right.kind in [.array, .map, .string]) { c.error('`in` can only be used with an array/map/string.', infix_expr.pos) } @@ -209,7 +209,8 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { if left_type == table.void_type || right_type == table.void_type { return table.void_type } - c.error('infix expr: cannot use `$right.name` (right) as `$left.name`', infix_expr.pos) + c.error('infix expr: cannot use `$right.name` (right expression) as `$left.name`', + infix_expr.pos) } if infix_expr.op.is_relational() { return table.bool_type @@ -752,9 +753,9 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { mut full_const_name := if it.mod == 'main' { it.name } else { it.mod + '.' + it.name } if obj := c.file.global_scope.find_const(full_const_name) { - if cint := const_int_value( obj ) { - fixed_size = cint - } + if cint := const_int_value(obj) { + fixed_size = cint + } } else { c.error('non existant integer const $full_const_name while initializing the size of a static array', array_init.pos) @@ -775,7 +776,7 @@ fn const_int_value(cfield ast.ConstField) ?int { if cint := is_const_integer(cfield) { return cint.val.int() } - return none + return none } fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index a67a8d9806..6aa3e526eb 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1376,7 +1376,10 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { g.write(', ') g.expr(node.right) g.write(')') - } else if node.op == .key_in { + } else if node.op in [.key_in, .not_in] { + if node.op == .not_in { + g.write('!') + } if right_sym.kind == .array { match node.right { ast.ArrayInit { diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 75ccbbf7d4..fe297191ad 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -720,6 +720,10 @@ pub fn (s mut Scanner) scan() token.Token { s.pos++ return s.new_token(.ne, '', 2) } + else if nextc == `i` && s.text[s.pos+2] == `n` && !s.text[s.pos+3].is_letter() { + s.pos += 2 + return s.new_token(.not_in, '', 3) + } else { return s.new_token(.not, '', 1) } diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index 32777f0344..a96b8a799c 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -44,6 +44,7 @@ pub enum Kind { str_dollar left_shift right_shift + not_in // !in // at // @ assign // = decl_assign // := @@ -167,6 +168,7 @@ fn build_token_str() []string { s[Kind.dotdot] = '..' s[Kind.ellipsis] = '...' s[Kind.comma] = ',' + s[Kind.not_in] = '!in' // s[Kind.at] = '@' s[Kind.semicolon] = ';' s[Kind.colon] = ':' @@ -381,7 +383,7 @@ pub fn (tok Token) precedence() int { .left_shift_assign, .right_shift_assign, .mult_assign, .xor_assign { return int(Precedence.assign) } - .key_in, .key_as { + .key_in, .not_in, .key_as { return int(Precedence.in_as) } .logical_or, .and { @@ -421,7 +423,7 @@ pub fn (k Kind) is_start_of_type() bool { pub fn (kind Kind) is_infix() bool { return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, // - .key_as, .ge, .le, .logical_or, .xor, + .key_as, .ge, .le, .logical_or, .xor, .not_in, // .and, .dot, .pipe, .amp, .left_shift, .right_shift] }