From 126ef0f5c2f4aeb128020c7c812effcf0b5bd24a Mon Sep 17 00:00:00 2001 From: Joe Conigliaro Date: Wed, 18 Mar 2020 19:56:19 +1100 Subject: [PATCH] checker/gen: add unchecked exprs & small fixes --- vlib/os/os.v | 4 ++-- vlib/v/checker/checker.v | 34 +++++++++++++++++----------------- vlib/v/gen/cgen.v | 30 +++++++++++++++--------------- vlib/v/parser/fn.v | 9 ++++++++- vlib/v/parser/parser.v | 21 ++++++++++++++++----- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/vlib/os/os.v b/vlib/os/os.v index 86880ad09d..f41b4a9c6a 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -235,14 +235,14 @@ fn vfopen(path, mode string) &C.FILE { // read_lines reads the file in `path` into an array of lines. pub fn read_lines(path string) ?[]string { buf := read_file(path) or { - return err + return error(err) } return buf.split_into_lines() } fn read_ulines(path string) ?[]ustring { lines := read_lines(path) or { - return err + return error(err) } // mut ulines := new_array(0, lines.len, sizeof(ustring)) mut ulines := []ustring diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 809473d113..ff076ea3da 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -82,7 +82,8 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type .placeholder { c.error('unknown struct: $typ_sym.name', struct_init.pos) } - .struct_ { + // string & array are also structs but .kind of string/array + .struct_, .string, .array { info := typ_sym.info as table.Struct if struct_init.fields.len == 0 { // Short syntax TODO check @@ -154,17 +155,15 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { } fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) { - if ast.expr_is_blank_ident(assign_expr.left) { - return - } left_type := c.expr(assign_expr.left) c.expected_type = left_type assign_expr.left_type = left_type - // assign_expr.left_type = left_type - // t := c.table.get_type_symbol(left_type) // println('setting exp type to $c.expected_type $t.name') right_type := c.expr(assign_expr.val) assign_expr.right_type = right_type + if ast.expr_is_blank_ident(assign_expr.left) { + return + } if !c.table.check(right_type, left_type) { left_type_sym := c.table.get_type_symbol(left_type) right_type_sym := c.table.get_type_symbol(right_type) @@ -174,18 +173,19 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) { pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { fn_name := call_expr.name + c.stmts(call_expr.or_block.stmts) // TODO: impl typeof properly (probably not going to be a fn call) if fn_name == 'typeof' { return table.string_type } // start hack: until v1 is fixed and c definitions are added for these - if fn_name == 'C.calloc' { - return table.byteptr_type - } - else if fn_name == 'C.exit' { - return table.void_type - } - else if fn_name == 'C.free' { + if fn_name in ['C.calloc', 'C.exit', 'C.free'] { + for arg in call_expr.args { + c.expr(arg.expr) + } + if fn_name == 'C.calloc' { + return table.byteptr_type + } return table.void_type } // end hack @@ -224,6 +224,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { } if !found { c.error('unknown fn: $fn_name', call_expr.pos) + return table.void_type } call_expr.return_type = f.return_type if f.is_c || call_expr.is_c { @@ -275,6 +276,7 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) method_call_expr.expr_type = typ typ_sym := c.table.get_type_symbol(typ) name := method_call_expr.name + c.stmts(method_call_expr.or_block.stmts) // println('method call $name $method_call_expr.pos.line_nr') if typ_sym.kind == .array && name in ['filter', 'clone', 'repeat'] { if name == 'filter' { @@ -285,12 +287,11 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) typ: array_info.elem_type }) } - else if name == 'repeat' { - c.expr(method_call_expr.args[0].expr) + for i, arg in method_call_expr.args { + c.expr(arg.expr) } // need to return `array_xxx` instead of `array` method_call_expr.return_type = typ - // method_call_expr.receiver_type = typ return typ } else if typ_sym.kind == .array && name in ['first', 'last'] { @@ -466,7 +467,6 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { // [1,2,3] if array_init.exprs.len > 0 && array_init.elem_type == table.void_type { for i, expr in array_init.exprs { - c.expr(expr) typ := c.expr(expr) // The first element's type if i == 0 { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index bb58f54c99..71ac73c435 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -412,7 +412,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { else { g.write('{$styp _ = ') g.expr(val) - g.writeln('}') + g.writeln(';}') } } else { @@ -575,7 +575,7 @@ fn (g mut Gen) expr(node ast.Expr) { else { g.write('{${g.typ(it.left_type)} _ = ') g.expr(it.val) - g.writeln('}') + g.writeln(';}') } } else { @@ -732,20 +732,20 @@ fn (g mut Gen) expr(node ast.Expr) { } } ast.MethodCallExpr { - mut receiver_name := 'TODO' // TODO: there are still due to unchecked exprs (opt/some fn arg) - if it.expr_type != 0 { - typ_sym := g.table.get_type_symbol(it.expr_type) - // rec_sym := g.table.get_type_symbol(it.receiver_type) - receiver_name = typ_sym.name - if typ_sym.kind == .array && it.name in - // TODO performance, detect `array` method differently - ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'clone'] { - // && rec_sym.name == 'array' { - // && rec_sym.name == 'array' && receiver_name.starts_with('array') { - // `array_byte_clone` => `array_clone` - receiver_name = 'array' - } + if it.expr_type == 0 { + verror('method receiver type is 0, this means there are some uchecked exprs') + } + typ_sym := g.table.get_type_symbol(it.expr_type) + // rec_sym := g.table.get_type_symbol(it.receiver_type) + mut receiver_name := typ_sym.name + if typ_sym.kind == .array && it.name in + // TODO performance, detect `array` method differently + ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'clone'] { + // && rec_sym.name == 'array' { + // && rec_sym.name == 'array' && receiver_name.starts_with('array') { + // `array_byte_clone` => `array_clone` + receiver_name = 'array' } name := '${receiver_name}_$it.name'.replace('.', '__') // if it.receiver_type != 0 { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index f1cf122460..c2b32f5f86 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -17,12 +17,19 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { mut or_stmts := []ast.Stmt if p.tok.kind == .key_orelse { p.next() - or_stmts = p.parse_block() + p.open_scope() + p.scope.register_var(ast.Var{ + name: 'err' + typ: table.type_to_optional(table.string_type) + }) + or_stmts = p.parse_block_no_scope() + p.close_scope() } node := ast.CallExpr{ name: fn_name args: args // tok: tok + pos: tok.position() is_c: is_c or_block: ast.OrExpr{ diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 230916a03d..ce60de1930 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -193,6 +193,14 @@ pub fn (p mut Parser) close_scope() { pub fn (p mut Parser) parse_block() []ast.Stmt { p.open_scope() + // println('parse block') + stmts := p.parse_block_no_scope() + p.close_scope() + // println('nr exprs in block = $exprs.len') + return stmts +} + +pub fn (p mut Parser) parse_block_no_scope() []ast.Stmt { p.check(.lcbr) mut stmts := []ast.Stmt if p.tok.kind != .rcbr { @@ -205,9 +213,6 @@ pub fn (p mut Parser) parse_block() []ast.Stmt { } } p.check(.rcbr) - // println('parse block') - p.close_scope() - // println('nr exprs in block = $exprs.len') return stmts } @@ -945,15 +950,21 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr { // p.close_scope() // } } - // Method call pos := p.tok.position() + // Method call if p.tok.kind == .lpar { p.next() args := p.call_args() mut or_stmts := []ast.Stmt if p.tok.kind == .key_orelse { p.next() - or_stmts = p.parse_block() + p.open_scope() + p.scope.register_var(ast.Var{ + name: 'err' + typ: table.type_to_optional(table.string_type) + }) + or_stmts = p.parse_block_no_scope() + p.close_scope() } mcall_expr := ast.MethodCallExpr{ expr: left