From ca8158ac412314b6c5c77cf615dfb1b6119ce56f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 28 May 2021 17:59:26 +0300 Subject: [PATCH] parser: handle casts in match expressions; c2v: minor fixes --- CHANGELOG.md | 7 +++++-- vlib/v/checker/check_types.v | 2 +- vlib/v/checker/checker.v | 28 ++++++++++++++++------------ vlib/v/gen/c/cgen.v | 9 +++++++-- vlib/v/parser/if_match.v | 4 ++-- vlib/v/tests/match_test.v | 2 +- 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 219cb9a5c0..ae656f34b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ -## V 0.2.4 --*Not yet released* +-*Not yet released, changelog is not full* +- String interpolation and struct stringers are now implemented in pure V +with a much cleaner and faster implementation. Previously libc's `sprintf` +was used. - Improved `unused variable` warning. Assigning to a variable no longer marks it as used. -- Bare metal support. +- Bare metal support. Vinix OS kernel is now being developed in V. ## V 0.2.2 - 0.2.3 *22 Jan 2021* diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index db3acf36e8..27cb5fcbaf 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -43,7 +43,7 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, exp_sym := c.table.get_type_symbol(expected) // unknown C types are set to int, allow int to be used for types like `&C.FILE` // eg. `C.fflush(C.stderr)` - error: cannot use `int` as `&C.FILE` in argument 1 to `C.fflush` - if expected.is_ptr() && exp_sym.language == .c && exp_sym.kind == .placeholder + if expected.is_ptr() && exp_sym.language == .c && exp_sym.kind in [.placeholder, .struct_] && got == ast.int_type_idx { return } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4c68a7467d..1d7b1a592b 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -880,7 +880,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type { } if obj.is_stack_obj && !c.inside_unsafe { sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) - if !sym.is_heap() { + if !sym.is_heap() && !c.pref.translated { suggestion := if sym.kind == .struct_ { 'declaring `$sym.name` as `[heap]`' } else { @@ -1300,11 +1300,13 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) ast.Type { return ast.void_type } .and, .logical_or { - if infix_expr.left_type != ast.bool_type_idx { - c.error('left operand for `$infix_expr.op` is not a boolean', infix_expr.left.position()) - } - if infix_expr.right_type != ast.bool_type_idx { - c.error('right operand for `$infix_expr.op` is not a boolean', infix_expr.right.position()) + if !c.pref.translated { + if infix_expr.left_type != ast.bool_type_idx { + c.error('left operand for `$infix_expr.op` is not a boolean', infix_expr.left.position()) + } + if infix_expr.right_type != ast.bool_type_idx { + c.error('right operand for `$infix_expr.op` is not a boolean', infix_expr.right.position()) + } } if mut infix_expr.left is ast.InfixExpr { if infix_expr.left.op != infix_expr.op && infix_expr.left.op in [.logical_or, .and] { @@ -1334,7 +1336,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) ast.Type { c.error('only `==`, `!=`, `|` and `&` are defined on `[flag]` tagged `enum`, use an explicit cast to `int` if needed', infix_expr.pos) } - } else { + } else if !c.pref.translated { // Regular enums c.error('only `==` and `!=` are defined on `enum`, use an explicit cast to `int` if needed', infix_expr.pos) @@ -3075,7 +3077,7 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) { } if obj.is_stack_obj && !c.inside_unsafe { type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) - if !type_sym.is_heap() { + if !type_sym.is_heap() && !c.pref.translated { suggestion := if type_sym.kind == .struct_ { 'declaring `$type_sym.name` as `[heap]`' } else { @@ -3331,7 +3333,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { } if obj.is_stack_obj && !c.inside_unsafe { type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) - if !type_sym.is_heap() { + if !type_sym.is_heap() && !c.pref.translated { suggestion := if type_sym.kind == .struct_ { 'declaring `$type_sym.name` as `[heap]`' } else { @@ -6274,14 +6276,16 @@ pub fn (mut c Checker) mark_as_referenced(mut node ast.Expr) { obj = c.fn_scope.find_var(node.obj.name) or { obj } } type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) - if obj.is_stack_obj && !type_sym.is_heap() { + if obj.is_stack_obj && !type_sym.is_heap() && !c.pref.translated { suggestion := if type_sym.kind == .struct_ { 'declaring `$type_sym.name` as `[heap]`' } else { 'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`' } - c.error('`$node.name` cannot be referenced outside `unsafe` blocks as it might be stored on stack. Consider ${suggestion}.', - node.pos) + if !c.pref.translated { + c.error('`$node.name` cannot be referenced outside `unsafe` blocks as it might be stored on stack. Consider ${suggestion}.', + node.pos) + } } else if type_sym.kind == .array_fixed { c.error('cannot reference fixed array `$node.name` outside `unsafe` blocks as it is supposed to be stored on stack', node.pos) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 9e93305910..76ceceeb5c 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3137,6 +3137,7 @@ fn (mut g Gen) expr(node ast.Expr) { } ast.EnumVal { // g.write('${it.mod}${it.enum_name}_$it.val') + // g.enum_expr(node) styp := g.typ(node.typ) g.write('${styp}_$node.val') } @@ -3482,8 +3483,12 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { fn (mut g Gen) enum_expr(node ast.Expr) { match node { - ast.EnumVal { g.write(node.val) } - else { g.expr(node) } + ast.EnumVal { + g.write(node.val) + } + else { + g.expr(node) + } } } diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 424a538f46..199a07e736 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -178,8 +178,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr { is_else = true p.next() } else if (p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) - && (p.tok.lit in ast.builtin_type_names || p.tok.lit[0].is_capital() - || (p.peek_tok.kind == .dot && p.peek_token(2).lit.len > 0 + && (((p.tok.lit in ast.builtin_type_names || p.tok.lit[0].is_capital()) + && p.peek_tok.kind != .lpar) || (p.peek_tok.kind == .dot && p.peek_token(2).lit.len > 0 && p.peek_token(2).lit[0].is_capital()))) || p.tok.kind == .lsbr { mut types := []ast.Type{} for { diff --git a/vlib/v/tests/match_test.v b/vlib/v/tests/match_test.v index 59edad535d..f86f6a2b13 100644 --- a/vlib/v/tests/match_test.v +++ b/vlib/v/tests/match_test.v @@ -19,7 +19,7 @@ fn test_match_integers() { println('three') b = 3 } - 4 { + int(4) { println('four') } else {