diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 737843b129..16ee005287 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -526,6 +526,7 @@ fn (c mut Checker) stmt(node ast.Stmt) { match mut node { ast.AssignStmt { c.assign_stmt(mut it) + c.expected_type = table.void_type } // ast.Attr {} // ast.CompIf {} @@ -544,6 +545,7 @@ fn (c mut Checker) stmt(node ast.Stmt) { } ast.ExprStmt { c.expr(it.expr) + c.expected_type = table.void_type } ast.FnDecl { c.expected_type = table.void_type diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 6e7e99cde6..b4380686be 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -23,6 +23,7 @@ mut: is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc optionals []string // to avoid duplicates TODO perf, use map inside_ternary bool // ?: comma separated statements on a single line + stmt_start_pos int } pub fn cgen(files []ast.File, table &table.Table) string { @@ -199,6 +200,7 @@ fn (g mut Gen) stmts(stmts []ast.Stmt) { } fn (g mut Gen) stmt(node ast.Stmt) { + g.stmt_start_pos = g.out.len // println('cgen.stmt()') // g.writeln('//// stmt start') match node { @@ -747,6 +749,10 @@ fn (g mut Gen) expr(node ast.Expr) { typ_sym := g.table.get_type_symbol(it.receiver_type) // rec_sym := g.table.get_type_symbol(it.receiver_type) mut receiver_name := typ_sym.name + if typ_sym.kind == .array && it.name == 'filter' { + g.gen_filter(it) + return + } if typ_sym.kind == .array && it.name in // TODO performance, detect `array` method differently ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', @@ -1599,6 +1605,35 @@ fn (g &Gen) sort_structs(types []table.TypeSymbol) []table.TypeSymbol { return types_sorted } +fn (g mut Gen) gen_filter(node ast.MethodCallExpr) { + tmp := g.new_tmp_var() + buf := g.out.buf[g.stmt_start_pos..] + s := string(buf.clone()) // the already generated part of current statement + g.out.go_back(s.len) + // println('filter s="$s"') + sym := g.table.get_type_symbol(node.return_type) + if sym.kind != .array { + verror('filter() requires an array') + } + info := sym.info as table.Array + styp := g.typ(node.return_type) + elem_type_str := g.typ(info.elem_type) + g.write('\nint ${tmp}_len = ') + g.expr(node.expr) + g.writeln('.len;') + g.writeln('$styp $tmp = new_array(0, ${tmp}_len, sizeof($elem_type_str));') + g.writeln('for (int i = 0; i < ${tmp}_len; i++) {') + g.write(' $elem_type_str it = (($elem_type_str*) ') + g.expr(node.expr) + g.writeln('.data)[i];') + g.write('if (') + g.expr(node.args[0].expr) // the first arg is the filter condition + g.writeln(') array_push(&$tmp, &it); \n }') + g.write(s) + g.write(' ') + g.write(tmp) +} + fn op_to_fn_name(name string) string { return match name { '+'{