From f965ddae497099c2280a0c3b8e1c0956010a064e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 16 Aug 2020 19:16:59 +0200 Subject: [PATCH] parser: handle several errors in types; cgen: objC includes --- doc/docs.md | 3 ++- .../tests/unknown_method_suggest_name.out | 6 +++-- vlib/v/gen/cgen.v | 12 ++++++++-- vlib/v/gen/fn.v | 2 ++ vlib/v/parser/parse_type.v | 10 ++++++++ vlib/v/parser/struct.v | 23 ++++++++++++++----- vlib/v/util/suggestions.v | 6 ++--- 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index cd11ae784d..9068c95d90 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -4,7 +4,8 @@ V is a statically typed compiled programming language designed for building maintainable software. -It's similar to Go and its design has also been influenced by Oberon, Rust, Swift, and Python. +It's similar to Go and its design has also been influenced by Oberon, Rust, Swift, +Kotlin, and Python. V is a very simple language. Going through this documentation will take you about half an hour, and by the end of it you will have pretty much learned the entire language. diff --git a/vlib/v/checker/tests/unknown_method_suggest_name.out b/vlib/v/checker/tests/unknown_method_suggest_name.out index 7f856b44e8..080a24f3ee 100644 --- a/vlib/v/checker/tests/unknown_method_suggest_name.out +++ b/vlib/v/checker/tests/unknown_method_suggest_name.out @@ -1,11 +1,13 @@ -vlib/v/checker/tests/unknown_method_suggest_name.v:7:2: error: unknown type `hash.crc32.Crc33`. Did you mean `crc32.Crc32` ? +vlib/v/checker/tests/unknown_method_suggest_name.v:7:2: error: unknown type `hash.crc32.Crc33`. +Did you mean `crc32.Crc32`? 5 | y int 6 | z int 7 | ccc crc32.Crc33 | ~~~~~~~~~~~~~~~ 8 | } 9 | -vlib/v/checker/tests/unknown_method_suggest_name.v:27:9: error: unknown method: `Point.tranzlate`. Did you mean `translate` ? +vlib/v/checker/tests/unknown_method_suggest_name.v:27:9: error: unknown method: `Point.tranzlate`. +Did you mean `translate`? 25 | p := Point{1, 2, 3} 26 | v := Vector{5, 5, 10} 27 | z := p.tranzlate(v) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index d4bd313b89..53da273556 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -863,8 +863,14 @@ fn (mut g Gen) stmt(node ast.Stmt) { // #include etc typ := node.val.all_before(' ') if typ == 'include' { - g.includes.writeln('// added by module `$node.mod`:') - g.includes.writeln('#$node.val') + if node.val.contains('.m') { + // Objective C code import, include it after V types, so that e.g. `string` is + // available there + g.definitions.writeln('#$node.val') + } else { + g.includes.writeln('// added by module `$node.mod`:') + g.includes.writeln('#$node.val') + } } if typ == 'define' { g.includes.writeln('#$node.val') @@ -880,6 +886,8 @@ fn (mut g Gen) stmt(node ast.Stmt) { ast.Return { g.write_defer_stmts_when_needed() if g.pref.autofree { + g.writeln('// ast.Return free') + // g.autofree_scope_vars(node.pos.pos) g.write_autofree_stmts_when_needed(node) } g.return_statement(node) diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index d6542b8dc5..55aacbaca5 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -641,6 +641,8 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) { g.expr(arg.expr) } else if g.autofree && g.pref.experimental && arg.typ == table.string_type && g.tmp_idxs.len > 0 && i in g.tmp_idxs { + // Save expressions in temp variables so that they can be freed later. + // `foo(str + str2) => x := str + str2; foo(x); x.free()` g.write('_arg_expr_${g.called_fn_name}_$i') } else { g.ref_or_deref_arg(arg, expected_types[i]) diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 37c8a4b4f3..ec16e8ca71 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -141,6 +141,9 @@ pub fn (mut p Parser) parse_type() table.Type { nr_muls++ p.next() } + if p.tok.kind == .mul { + p.error('use `&Type` instead of `*Type` when declaring references') + } // &Type for p.tok.kind == .amp { nr_muls++ @@ -190,6 +193,9 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr, check_dot p.check(.dot) // prefix with full module name = '${p.imports[name]}.$p.tok.lit' + if !p.tok.lit[0].is_capital() { + p.error('imported types must start with a capital letter') + } } else if p.expr_mod != '' { name = p.expr_mod + '.' + name } else if p.mod != 'builtin' && name !in p.table.type_idxs && name.len > 1 { @@ -224,6 +230,10 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr, check_dot defer { p.next() } + if name == '' { + // This means the developer is using some wrong syntax like `x: int` instead of `x int` + p.error('bad type syntax') + } match name { 'voidptr' { return table.voidptr_type diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 5ed7655e26..49da8dc27a 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -36,6 +36,11 @@ fn (mut p Parser) struct_decl() ast.StructDecl { } name_pos := p.tok.position() mut name := p.check_name() + // defer { + // if name.contains('App') { + // println('end of struct decl $name') + // } + // } if name.len == 1 && name[0].is_capital() { p.error_with_pos('single letter capital names are reserved for generic template types.', name_pos) @@ -153,12 +158,11 @@ fn (mut p Parser) struct_decl() ast.StructDecl { pos: field_start_pos.pos len: p.tok.position().pos - field_start_pos.pos } - /* - if name == '_net_module_s' { - s := p.table.get_type_symbol(typ) - println('XXXX' + s.str()) - } - */ + // if name == '_net_module_s' { + // if name.contains('App') { + // s := p.table.get_type_symbol(typ) + // println('struct decl field type ' + s.str()) + // } // Comments after type (same line) line_pos := field_pos.line_nr for p.tok.kind == .comment && line_pos + 1 == p.tok.line_nr { @@ -267,6 +271,13 @@ fn (mut p Parser) struct_decl() ast.StructDecl { fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit { first_pos := p.tok.position() + /* + defer { + if p.fileis('x.v') { + p.warn('end of struct init $short_syntax') + } + } + */ typ := if short_syntax { table.void_type } else { p.parse_type() } p.expr_mod = '' // sym := p.table.get_type_symbol(typ) diff --git a/vlib/v/util/suggestions.v b/vlib/v/util/suggestions.v index b64c8e101f..d5df72a5ac 100644 --- a/vlib/v/util/suggestions.v +++ b/vlib/v/util/suggestions.v @@ -38,11 +38,11 @@ pub fn new_suggestion(wanted string, possibilities []string) Suggestion { } pub fn (mut s Suggestion) add(val string) { - if val in [ s.wanted, s.swanted ] { + if val in [s.wanted, s.swanted] { return } sval := short_module_name(val) - if sval in [ s.wanted, s.swanted ] { + if sval in [s.wanted, s.swanted] { return } s.known << Possibility{ @@ -69,7 +69,7 @@ pub fn (s Suggestion) say(msg string) string { if top_posibility.similarity > 0.10 { val := top_posibility.value if !val.starts_with('[]') { - res += '. Did you mean `$val` ?' + res += '.\nDid you mean `$val`?' } } }