Skip to content

Instantly share code, notes, and snippets.

@Delta456
Created October 17, 2020 14:37
Show Gist options
  • Select an option

  • Save Delta456/e5ecb408eabb9a32e33d63cd1da04c79 to your computer and use it in GitHub Desktop.

Select an option

Save Delta456/e5ecb408eabb9a32e33d63cd1da04c79 to your computer and use it in GitHub Desktop.

Revisions

  1. Delta456 created this gist Oct 17, 2020.
    41 changes: 41 additions & 0 deletions check_cast_type.v
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,41 @@
    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

    }
    76 changes: 76 additions & 0 deletions checker.v
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    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)
    }