parser: handle casts in match expressions; c2v: minor fixes

pull/10246/head
Alexander Medvednikov 2021-05-28 17:59:26 +03:00
parent 9fab4af3f1
commit ca8158ac41
6 changed files with 32 additions and 20 deletions

View File

@ -1,7 +1,10 @@
-## V 0.2.4 -## 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. - 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 ## V 0.2.2 - 0.2.3
*22 Jan 2021* *22 Jan 2021*

View File

@ -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) 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` // 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` // 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 { && got == ast.int_type_idx {
return return
} }

View File

@ -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 { if obj.is_stack_obj && !c.inside_unsafe {
sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) 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_ { suggestion := if sym.kind == .struct_ {
'declaring `$sym.name` as `[heap]`' 'declaring `$sym.name` as `[heap]`'
} else { } else {
@ -1300,11 +1300,13 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) ast.Type {
return ast.void_type return ast.void_type
} }
.and, .logical_or { .and, .logical_or {
if infix_expr.left_type != ast.bool_type_idx { if !c.pref.translated {
c.error('left operand for `$infix_expr.op` is not a boolean', infix_expr.left.position()) 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 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 mut infix_expr.left is ast.InfixExpr {
if infix_expr.left.op != infix_expr.op && infix_expr.left.op in [.logical_or, .and] { 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', c.error('only `==`, `!=`, `|` and `&` are defined on `[flag]` tagged `enum`, use an explicit cast to `int` if needed',
infix_expr.pos) infix_expr.pos)
} }
} else { } else if !c.pref.translated {
// Regular enums // Regular enums
c.error('only `==` and `!=` are defined on `enum`, use an explicit cast to `int` if needed', c.error('only `==` and `!=` are defined on `enum`, use an explicit cast to `int` if needed',
infix_expr.pos) 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 { if obj.is_stack_obj && !c.inside_unsafe {
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) 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_ { suggestion := if type_sym.kind == .struct_ {
'declaring `$type_sym.name` as `[heap]`' 'declaring `$type_sym.name` as `[heap]`'
} else { } 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 { if obj.is_stack_obj && !c.inside_unsafe {
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) 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_ { suggestion := if type_sym.kind == .struct_ {
'declaring `$type_sym.name` as `[heap]`' 'declaring `$type_sym.name` as `[heap]`'
} else { } 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 } obj = c.fn_scope.find_var(node.obj.name) or { obj }
} }
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0)) 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_ { suggestion := if type_sym.kind == .struct_ {
'declaring `$type_sym.name` as `[heap]`' 'declaring `$type_sym.name` as `[heap]`'
} else { } else {
'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`' '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}.', if !c.pref.translated {
node.pos) 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 { } 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', c.error('cannot reference fixed array `$node.name` outside `unsafe` blocks as it is supposed to be stored on stack',
node.pos) node.pos)

View File

@ -3137,6 +3137,7 @@ fn (mut g Gen) expr(node ast.Expr) {
} }
ast.EnumVal { ast.EnumVal {
// g.write('${it.mod}${it.enum_name}_$it.val') // g.write('${it.mod}${it.enum_name}_$it.val')
// g.enum_expr(node)
styp := g.typ(node.typ) styp := g.typ(node.typ)
g.write('${styp}_$node.val') 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) { fn (mut g Gen) enum_expr(node ast.Expr) {
match node { match node {
ast.EnumVal { g.write(node.val) } ast.EnumVal {
else { g.expr(node) } g.write(node.val)
}
else {
g.expr(node)
}
} }
} }

View File

@ -178,8 +178,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
is_else = true is_else = true
p.next() p.next()
} else if (p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) } 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.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.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 { && p.peek_token(2).lit[0].is_capital()))) || p.tok.kind == .lsbr {
mut types := []ast.Type{} mut types := []ast.Type{}
for { for {

View File

@ -19,7 +19,7 @@ fn test_match_integers() {
println('three') println('three')
b = 3 b = 3
} }
4 { int(4) {
println('four') println('four')
} }
else { else {