diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index f0877a7f02..cf13b3d389 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -505,7 +505,8 @@ pub fn (mut f Fmt) struct_field_expr(fexpr ast.Expr) { fn (f &Fmt) type_to_str(t table.Type) string { mut res := f.table.type_to_str(t) - if res.ends_with('_ptr') { + + for res.ends_with('_ptr') { // type_ptr => &type res = res[0..res.len - 4] start_pos := 2 * res.count('[]') diff --git a/vlib/v/fmt/tests/type_ptr_keep.vv b/vlib/v/fmt/tests/type_ptr_keep.vv index 88ec016566..903a35524a 100644 --- a/vlib/v/fmt/tests/type_ptr_keep.vv +++ b/vlib/v/fmt/tests/type_ptr_keep.vv @@ -1,13 +1,19 @@ const ( - x = &Test{} - y = []&Test{} - z = &[]&Test{} + x = &Test{} + y = []&Test{} + z = &[]&Test{} + xx = &&Test{} + yy = []&&Test{} + zz = &&[]&&Test{} ) fn test_type_ptr() { _ := &Test{} _ := []&Test{} _ := &[]&Test{} + _ := &&Test{} + _ := []&&Test{} + _ := &&[]&&Test{} } struct Test { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index e4d3d7c97c..b71b5324a6 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -361,7 +361,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { mut args := []table.Arg{} mut is_variadic := false // `int, int, string` (no names, just types) - types_only := p.tok.kind in [.amp, .and, .ellipsis] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || + types_only := p.tok.kind in [.amp, .ellipsis] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || p.peek_tok.kind == .rpar // TODO copy pasta, merge 2 branches if types_only { diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 6ad3c961cc..a1211fa976 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -111,12 +111,8 @@ pub fn (mut p Parser) parse_type() table.Type { p.next() } // &Type - for p.tok.kind in [.and, .amp] { - if p.tok.kind == .and { - nr_muls += 2 - } else { - nr_muls++ - } + for p.tok.kind == .amp { + nr_muls++ p.next() } diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index afc5d00d5f..aa72459d6d 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -641,6 +641,15 @@ pub fn (mut s Scanner) buffer_scan() token.Token { } } +[inline] +fn (s Scanner) look_ahead(n int) byte { + if s.pos + n < s.text.len { + return s.text[s.pos + n] + } else { + return `\0` + } +} + fn (mut s Scanner) text_scan() token.Token { // if s.comments_mode == .parse_comments { // println('\nscan()') @@ -676,14 +685,14 @@ fn (mut s Scanner) text_scan() token.Token { } // handle each char c := s.text[s.pos] - nextc := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } + nextc := s.look_ahead(1) // name or keyword if util.is_name_char(c) { name := s.ident_name() // tmp hack to detect . in ${} // Check if not .eof to prevent panic - next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } + next_char := s.look_ahead(1) kind := token.keywords[name] if kind != .unknown { if kind == .key_fn { @@ -738,7 +747,7 @@ fn (mut s Scanner) text_scan() token.Token { if c == `)` && s.is_inter_start { s.is_inter_end = true s.is_inter_start = false - next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } + next_char := s.look_ahead(1) if next_char == s.quote { s.is_inside_string = false } @@ -849,7 +858,9 @@ fn (mut s Scanner) text_scan() token.Token { s.pos++ return s.new_token(.and_assign, '', 2) } - if nextc == `&` { + + afternextc := s.look_ahead(2) + if nextc == `&` && afternextc.is_space() { s.pos++ return s.new_token(.and, '', 2) } diff --git a/vlib/v/scanner/scanner_test.v b/vlib/v/scanner/scanner_test.v index 609d257f49..34dc113cee 100644 --- a/vlib/v/scanner/scanner_test.v +++ b/vlib/v/scanner/scanner_test.v @@ -44,8 +44,7 @@ fn fn_name_mod_level_high_order(cb fn(int)) { cb(1) } -fn test_scan() { - text := 'println(2 + 3)' +fn scan_kinds(text string) []token.Kind { mut scanner := new_scanner(text, .skip_comments) mut token_kinds := []token.Kind{} for { @@ -55,6 +54,11 @@ fn test_scan() { } token_kinds << tok.kind } + return token_kinds +} + +fn test_scan() { + token_kinds := scan_kinds('println(2 + 3)') assert token_kinds.len == 6 assert token_kinds[0] == .name assert token_kinds[1] == .lpar @@ -122,3 +126,55 @@ fn test_vmod_file() { assert content.contains('version:') assert content.contains('description:') } + +fn test_reference() { + mut result := scan_kinds('true && false') + assert result.len == 3 + assert result[0] == .key_true + assert result[1] == .and + assert result[2] == .key_false + + result = scan_kinds('&foo') + assert result.len == 2 + assert result[0] == .amp + assert result[1] == .name + + result = scan_kinds('[]&foo') + assert result.len == 4 + assert result[0] == .lsbr + assert result[1] == .rsbr + assert result[2] == .amp + assert result[3] == .name + + result = scan_kinds('&[]&foo') + assert result.len == 5 + assert result[0] == .amp + assert result[1] == .lsbr + assert result[2] == .rsbr + assert result[3] == .amp + assert result[4] == .name + + result = scan_kinds('&&foo') + assert result.len == 3 + assert result[0] == .amp + assert result[1] == .amp + assert result[2] == .name + + result = scan_kinds('[]&&foo') + assert result.len == 5 + assert result[0] == .lsbr + assert result[1] == .rsbr + assert result[2] == .amp + assert result[3] == .amp + assert result[4] == .name + + result = scan_kinds('&&[]&&foo') + assert result.len == 7 + assert result[0] == .amp + assert result[1] == .amp + assert result[2] == .lsbr + assert result[3] == .rsbr + assert result[4] == .amp + assert result[5] == .amp + assert result[6] == .name +} diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 247ef093a2..6d402800e7 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -274,7 +274,7 @@ pub fn (t &Table) known_type(name string) bool { pub fn (t &Table) array_name(elem_type Type, nr_dims int) string { elem_type_sym := t.get_type_symbol(elem_type) return 'array_${elem_type_sym.name}' + if elem_type.is_ptr() { - '_ptr' + '_ptr'.repeat(elem_type.nr_muls()) } else { '' } + if nr_dims > 1 { diff --git a/vlib/v/tests/double_ref_deref_test.v b/vlib/v/tests/double_ref_deref_test.v new file mode 100644 index 0000000000..96fc448d06 --- /dev/null +++ b/vlib/v/tests/double_ref_deref_test.v @@ -0,0 +1,10 @@ +fn process(foo &&int) int { + return **foo +} + +fn test_ref_deref() { + foo := 12 + bar := &foo + fiz := process(&bar) + assert fiz == 12 +}