Created
October 17, 2020 14:37
-
-
Save Delta456/e5ecb408eabb9a32e33d63cd1da04c79 to your computer and use it in GitHub Desktop.
check_cast_type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub fn (mut c Checker) can_type_cast(from table.Type, to table.Type) bool { | |
from_type_sym := c.table.get_type_symbol(from) | |
to_type_sym := c.table.get_type_symbol(to) | |
// check basic types | |
if c.check_types(from, to) { | |
return true | |
} | |
if to == table.bool_type || to_type_sym.kind == .none_ || from == table.none_type { | |
return false | |
} | |
if from == table.byte_type { | |
if to.is_int() || to.is_float() { | |
return true | |
} | |
return false | |
} | |
if to == table.string_type { | |
// nothing can be casted to string | |
return false | |
} | |
if to_type_sym.kind == .byte { | |
// TODO: check for rune overflow | |
if from.is_int() || from.is_float() || from == table.voidptr_type || from_type_sym.kind == .enum_ { | |
return true | |
} | |
return false | |
} | |
if to_type_sym.kind == .struct_ && !to.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef { | |
// For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard | |
if from_type_sym.kind == .struct_ && !from.is_ptr() { | |
from_type_info := from_type_sym.info as table.Struct | |
to_type_info := to_type_sym.info as table.Struct | |
return c.check_struct_signature(from_type_info, to_type_info) | |
} | |
return false | |
} | |
return true | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
node.expr_type = c.expr(node.expr) | |
from_type_sym := c.table.get_type_symbol(node.expr_type) | |
to_type_sym := c.table.get_type_symbol(node.typ) | |
expr_is_ptr := node.expr_type.is_ptr() || node.expr_type.idx() in table.pointer_type_idxs | |
if expr_is_ptr && to_type_sym.kind == .string && !node.in_prexpr { | |
if node.has_arg { | |
c.warn('to convert a C string buffer pointer to a V string, please use x.vstring_with_len(len) instead of string(x,len)', | |
node.pos) | |
} else { | |
c.warn('to convert a C string buffer pointer to a V string, please use x.vstring() instead of string(x)', | |
node.pos) | |
} | |
} | |
if !c.can_type_cast(node.expr_type, node.typ) { | |
if node.expr_type == table.byte_type { | |
c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.', | |
node.pos) | |
} | |
if (node.typ == table.string_type && from_type_sym.kind in [.any_int, .int, .byte, .byteptr, .bool]) || | |
(from_type_sym.kind == .array && from_type_sym.name == 'array_byte') { | |
type_name := c.table.type_to_str(node.expr_type) | |
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', | |
node.pos) | |
} | |
/*node.expr_type == table.byte_type && to_type_sym.kind == .string {*/ | |
} | |
if to_type_sym.kind == .sum_type { | |
if node.expr_type in [table.any_int_type, table.any_flt_type] { | |
node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type }) | |
} | |
if !c.table.sumtype_has_variant(node.typ, node.expr_type) { | |
c.error('cannot cast `$from_type_sym.source_name` to `$to_type_sym.source_name`', | |
node.pos) | |
} | |
} /*else if node.typ == table.string_type && | |
(from_type_sym.kind in [.any_int, .int, .byte, .byteptr] || | |
(from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) { | |
type_name := c.table.type_to_str(node.expr_type) | |
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', | |
node.pos) | |
}*/ else if node.expr_type == table.string_type { | |
if to_type_sym.kind != .alias { | |
mut error_msg := 'cannot cast a string' | |
if node.expr is ast.StringLiteral { | |
str_lit := node.expr as ast.StringLiteral | |
if str_lit.val.len == 1 { | |
error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'" | |
} | |
} | |
c.error(error_msg, node.pos) | |
} | |
} else if !c.can_type_cast(node.expr_type, node.typ) { | |
/*else if to_type_sym.kind == .byte && | |
node.expr_type != table.voidptr_type && from_type_sym.kind != .enum_ && !node.expr_type.is_int() && | |
!node.expr_type.is_float() && !node.expr_type.is_ptr() {*/ | |
type_name := c.table.type_to_str(node.expr_type) | |
c.error('cannot cast type `$type_name` to `byte`', node.pos) | |
} else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef { | |
// For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard | |
if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { | |
from_type_info := from_type_sym.info as table.Struct | |
to_type_info := to_type_sym.info as table.Struct | |
if !c.check_struct_signature(from_type_info, to_type_info) { | |
c.error('cannot convert struct `$from_type_sym.source_name` to struct `$to_type_sym.source_name`', | |
node.pos) | |
} | |
} else { | |
type_name := c.table.type_to_str(node.expr_type) | |
c.error('cannot cast `$type_name` to struct', node.pos) | |
} | |
} else if node.typ == table.bool_type { | |
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos) | |
} else if node.expr_type == table.none_type { | |
type_name := c.table.type_to_str(node.typ) | |
c.error('cannot cast `none` to `$type_name`', node.pos) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment