all: `!is` operator

pull/5179/head
Alexander Medvednikov 2020-06-02 16:18:12 +02:00
parent 4e51867612
commit fb3e52ca63
7 changed files with 43 additions and 26 deletions

View File

@ -546,7 +546,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
.right_shift {
return c.check_shift(left_type, right_type, left_pos, right_pos)
}
.key_is {
.key_is, .not_is {
type_expr := infix_expr.right as ast.Type
typ_sym := c.table.get_type_symbol(type_expr.typ)
if typ_sym.kind == .placeholder {

View File

@ -180,10 +180,10 @@ pub fn (mut d Doc) generate() ?bool {
// parse files
mut file_asts := []ast.File{}
// TODO: remove later for vlib
comments_mode := if d.with_comments {
scanner.CommentsMode.parse_comments
} else {
scanner.CommentsMode.skip_comments
comments_mode := if d.with_comments {
scanner.CommentsMode.parse_comments
} else {
scanner.CommentsMode.skip_comments
}
for file in v_files {
file_ast := parser.parse_file(
@ -222,13 +222,14 @@ pub fn (mut d Doc) generate() ?bool {
for si, stmt in stmts {
if stmt is ast.Comment { continue }
if !(stmt is ast.Module) {
//if !(stmt is ast.Module) {
if stmt !is ast.Module {
// todo: accumulate consts
mut name := d.get_name(stmt)
signature := d.get_signature(stmt)
pos := d.get_pos(stmt)
if !signature.starts_with('pub') && d.pub_only {
if !signature.starts_with('pub') && d.pub_only {
continue
}
@ -268,7 +269,7 @@ pub fn (mut d Doc) generate() ?bool {
last_comment := d.contents[d.contents.len-1].comment
d.contents[d.contents.len-1].comment = last_comment + '\n' + write_comment_bw(stmts, si-1)
}
}
}
}
}
@ -286,4 +287,4 @@ pub fn generate(input_path string, pub_only bool, with_comments bool) ?Doc {
}
return doc
}
}

View File

@ -1744,7 +1744,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
// g.infix_op = node.op
left_type := if node.left_type == table.t_type { g.cur_generic_type } else { node.left_type }
left_sym := g.table.get_type_symbol(left_type)
if node.op == .key_is {
if node.op in [.key_is, .not_is] {
g.is_expr(node)
return
}
@ -3767,6 +3767,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
}
fn (mut g Gen) is_expr(node ast.InfixExpr) {
eq := if node.op == .key_is { '==' } else { '!=' }
g.expr(node.left)
if node.left_type.is_ptr() {
g.write('->')
@ -3775,14 +3776,14 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
}
sym := g.table.get_type_symbol(node.left_type)
if sym.kind == .interface_ {
g.write('_interface_idx == ')
g.write('_interface_idx $eq ')
// `_Animal_Dog_index`
sub_type := node.right as ast.Type
sub_sym := g.table.get_type_symbol(sub_type.typ)
g.write('_${sym.name}_${sub_sym.name}_index')
return
} else if sym.kind == .sum_type {
g.write('typ == ')
g.write('typ $eq ')
}
g.expr(node.right)
}

View File

@ -198,7 +198,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
pos := p.tok.position()
p.next()
mut right := ast.Expr{}
if op == .key_is {
if op in [.key_is, .not_is] {
p.expecting_type = true
}
right = p.expr(precedence)

View File

@ -946,6 +946,11 @@ pub fn (mut s Scanner) scan() token.Token {
s.pos += 2
return s.new_token(.not_in, '', 3)
}
else if nextc == `i` && s.text[s.pos+2] == `s` && s.text[s.pos+3].is_space() {
s.pos += 2
return s.new_token(.not_is, '', 3)
}
//
else {
return s.new_token(.not, '', 1)
}

View File

@ -11,6 +11,7 @@ struct IntegerLiteral {
fn handle(e Expr) string {
is_literal := e is IntegerLiteral
assert is_literal
assert !(e !is IntegerLiteral)
if e is IntegerLiteral {
println('int')
}
@ -39,8 +40,8 @@ fn test_assignment_and_push() {
mut expr1 := Expr{}
mut arr1 := []Expr{}
expr := IntegerLiteral{
val: '111'
}
val: '111'
}
arr1 << expr
match arr1[0] {
IntegerLiteral {
@ -54,24 +55,33 @@ fn test_assignment_and_push() {
}
// Test moving structs between master/sub arrays
type Master = Sub1 | Sub2
struct Sub1 {
mut:
val int
val int
name string
}
struct Sub2 {
name string
val int
val int
}
fn test_converting_down() {
mut out := []Master{}
out << Sub1 { val: 1, name: 'one' }
out << Sub2 { val: 2, name: 'two'}
out << Sub2 { val: 3, name: 'three'}
out << Sub1{
val: 1
name: 'one'
}
out << Sub2{
val: 2
name: 'two'
}
out << Sub2{
val: 3
name: 'three'
}
mut res := []Sub2{cap: out.len}
for d in out {
match d {
@ -79,10 +89,8 @@ fn test_converting_down() {
else {}
}
}
assert res[0].val == 2
assert res[0].name == 'two'
assert res[1].val == 3
assert res[1].name == 'three'
}

View File

@ -45,6 +45,7 @@ pub enum Kind {
left_shift
right_shift
not_in // !in
not_is // !is
// at // @
assign // =
decl_assign // :=
@ -169,6 +170,7 @@ fn build_token_str() []string {
s[Kind.ellipsis] = '...'
s[Kind.comma] = ','
s[Kind.not_in] = '!in'
s[Kind.not_is] = '!is'
// s[Kind.at] = '@'
s[Kind.semicolon] = ';'
s[Kind.colon] = ':'
@ -382,7 +384,7 @@ pub fn (tok Token) precedence() int {
.left_shift_assign, .right_shift_assign, .mult_assign, .xor_assign {
return int(Precedence.assign)
}
.key_in, .not_in, .key_as, .key_is {
.key_in, .not_in, .key_as, .key_is, .not_is {
return int(Precedence.in_as)
}
.logical_or, .and {
@ -422,7 +424,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, .not_in, .key_is,
.key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is, .not_is,
//
.and, .dot, .pipe, .amp, .left_shift, .right_shift]
}