diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 52445d96bd..8d66af686a 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -691,3 +691,8 @@ fn test_hex(){ st1 := [byte(0x41)].repeat(100) assert st1.hex() == "41".repeat(100) } + +fn test_array_with_cap() { + a := []int{cap:10, len:1 } + //assert a.len == 1 +} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 1905f10555..e7e701a1dd 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -444,6 +444,9 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type { if typ_sym.kind == .void && arg_typ_sym.kind == .string { continue } + if f.is_generic { + continue + } if typ_sym.kind == .array_fixed { } // println('fixed') @@ -1333,7 +1336,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { c.error('match 0 cond type', node.pos) } type_sym := c.table.get_type_symbol(cond_type) - // all_possible_left_subtypes is a histogram of // type => how many times it was used in the match mut all_possible_left_subtypes := map[string]int @@ -1343,7 +1345,7 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { match type_sym.info { table.SumType { for v in it.variants { - all_possible_left_subtypes[ int(v).str() ] = 0 + all_possible_left_subtypes[int(v).str()] = 0 } } table.Enum { @@ -1362,12 +1364,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { ast.Type { tidx := table.type_idx(it.typ) stidx := tidx.str() - all_possible_left_subtypes[ stidx ] = all_possible_left_subtypes[ stidx ] + 1 + all_possible_left_subtypes[stidx] = all_possible_left_subtypes[stidx] + + 1 } ast.EnumVal { - all_possible_left_enum_vals[ it.val ] = all_possible_left_enum_vals[ it.val ] + 1 + all_possible_left_enum_vals[it.val] = all_possible_left_enum_vals[it.val] + + 1 } - else{} + else {} } } } @@ -1376,20 +1380,22 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { unhandled := []string match type_sym.info { table.SumType { - for k,v in all_possible_left_subtypes { + for k, v in all_possible_left_subtypes { if v == 0 { err = true - unhandled << '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' + unhandled << '`' + c.table.type_to_str(table.new_type(k.int())) + '`' } if v > 1 { err = true - multiple_type_name := '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' - c.error('a match case for $multiple_type_name is handled more than once', node.pos) + multiple_type_name := '`' + c.table.type_to_str(table.new_type(k.int())) + + '`' + c.error('a match case for $multiple_type_name is handled more than once', + node.pos) } } } table.Enum { - for k,v in all_possible_left_enum_vals { + for k, v in all_possible_left_enum_vals { if v == 0 { err = true unhandled << '`.$k`' @@ -1397,11 +1403,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { if v > 1 { err = true multiple_enum_val := '`.$k`' - c.error('a match case for $multiple_enum_val is handled more than once', node.pos) + c.error('a match case for $multiple_enum_val is handled more than once', + node.pos) } } } - else { err = true } + else { + err = true + } } if err { if unhandled.len > 0 { @@ -1410,7 +1419,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { c.error(err_details, node.pos) } } - c.expected_type = cond_type mut ret_type := table.void_type for branch in node.branches { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 44e144b603..8ee20ea50b 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -553,6 +553,15 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write(it.val) } ast.MapInit { + if it.keys.len == 0 { + if it.value_type == 0 { + f.write('map[string]int') // TODO + return + } + f.write('map[string]') + f.write(f.type_to_str(it.value_type)) + return + } f.writeln('{') f.indent++ for i, key in it.keys { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 1319886c4a..07bb7c8fbd 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -212,9 +212,13 @@ pub fn (g mut Gen) typ(t table.Type) string { if table.type_is(t, .optional) { // Register an optional styp = 'Option_' + styp + if table.type_is_ptr(t) { + styp = styp.replace('*', '_ptr') + } if !(styp in g.optionals) { // println(styp) - g.typedefs2.writeln('typedef Option $styp;') + x := styp // .replace('*', '_ptr') // handle option ptrs + g.typedefs2.writeln('typedef Option $x;') g.optionals << styp } } @@ -1744,7 +1748,11 @@ fn (g mut Gen) return_statement(node ast.Return) { mut styp := g.typ(g.fn_decl.return_type) if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] != styp = styp[7..] // remove 'Option_' - g.write('opt_ok(& ($styp []) { ') + mut x := styp + if x.ends_with('_ptr') { + x = x.replace('_ptr', '*') + } + g.write('opt_ok(&($x/*X*/[]) { ') } g.write('($styp){') for i, expr in node.exprs { @@ -1783,9 +1791,13 @@ fn (g mut Gen) return_statement(node ast.Return) { } if !is_none && !is_error { styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' - g.write('/*:)$return_sym.name*/opt_ok(&($styp []) { ') + mut x := styp + if x.ends_with('_ptr') { + x = x.replace('_ptr', '*') + } + g.write('/*:)$return_sym.name*/opt_ok(&($x[]) { ') g.expr(node.exprs[0]) - g.writeln(' }, sizeof($styp));') + g.writeln(' }, sizeof($x));') return } // g.write('/*OPTIONAL*/') diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index d6a1b7ae2c..a74c0b1f47 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -141,7 +141,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl { p.next() } // - if p.tok.kind == .lt { + is_generic := p.tok.kind == .lt + if is_generic { p.next() p.next() p.check(.gt) @@ -169,6 +170,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { args: args return_type: return_type is_variadic: is_variadic + is_generic: is_generic }) } else { if is_c { @@ -185,6 +187,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { return_type: return_type is_variadic: is_variadic is_c: is_c + is_generic: is_generic }) } // Body diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 00f5884bd9..bf83aff806 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1351,15 +1351,12 @@ fn (p mut Parser) array_init() ast.ArrayInit { // p.check_comment() } line_nr := p.tok.line_nr - $if tinyc { // NB: do not remove the next line without testing // v selfcompilation with tcc first tcc_stack_bug := 12345 } - last_pos = p.tok.position() - p.check(.rsbr) // [100]byte if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { @@ -1376,6 +1373,22 @@ fn (p mut Parser) array_init() ast.ArrayInit { last_pos = p.tok.position() p.next() } + if p.tok.kind == .lcbr && exprs.len == 0 { + // `[]int{ len: 10, cap: 100}` syntax + p.next() + for p.tok.kind != .rcbr { + key := p.check_name() + p.check(.colon) + if !(key in ['len', 'cap', 'init']) { + p.error('wrong field `$key`, expecting `len`, `cap`, or `init`') + } + p.expr(0) + if p.tok.kind != .rcbr { + p.check(.comma) + } + } + p.check(.rcbr) + } pos := token.Position{ line_nr: first_pos.line_nr pos: first_pos.pos @@ -1594,7 +1607,9 @@ fn (p mut Parser) struct_decl() ast.StructDecl { // p.expr(0) default_expr = p.expr(0) match default_expr { - ast.EnumVal { it.typ = typ } + ast.EnumVal { + it.typ = typ + } // TODO: implement all types?? else {} } @@ -1865,8 +1880,8 @@ fn (p mut Parser) match_expr() ast.MatchExpr { if p.tok.kind == .key_else { is_else = true p.next() - } else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || - (p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { + } else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() && + !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { // Sum type match // if sym.kind == .sum_type { // p.warn('is sum') @@ -1993,7 +2008,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl { name := p.check_name() mut sum_variants := []table.Type if p.tok.kind == .assign { - p.next() // TODO require `=` + p.next() // TODO require `=` } if p.tok.kind == .key_fn { // function type: `type mycallback fn(string, int)` @@ -2005,7 +2020,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl { typ: fn_type } } - first_type := p.parse_type() // need to parse the first type before we can check if it's `type A = X | Y` + first_type := p.parse_type() // need to parse the first type before we can check if it's `type A = X | Y` if p.tok.kind == .pipe { p.check(.pipe) sum_variants << first_type diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 2f40bf1517..270a26f89a 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -25,6 +25,7 @@ pub: return_type Type is_variadic bool is_c bool + is_generic bool } pub struct Arg {