checker: move check_types() on top; small c2v fixes
parent
0021fbbaa9
commit
8f9f681e81
|
@ -6,6 +6,74 @@ module checker
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.token
|
import v.token
|
||||||
|
|
||||||
|
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
|
||||||
|
pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
||||||
|
if got == expected {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
got_is_ptr := got.is_ptr()
|
||||||
|
exp_is_ptr := expected.is_ptr()
|
||||||
|
if got_is_ptr && exp_is_ptr {
|
||||||
|
if got.nr_muls() != expected.nr_muls() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exp_idx := expected.idx()
|
||||||
|
got_idx := got.idx()
|
||||||
|
if exp_idx == got_idx {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if exp_idx == ast.voidptr_type_idx || exp_idx == ast.byteptr_type_idx
|
||||||
|
|| (expected.is_ptr() && expected.deref().idx() == ast.byte_type_idx) {
|
||||||
|
if got.is_ptr() || got.is_pointer() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// allow direct int-literal assignment for pointers for now
|
||||||
|
// maybe in the future optionals should be used for that
|
||||||
|
if expected.is_real_pointer() {
|
||||||
|
if got == ast.int_literal_type {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if got_idx == ast.voidptr_type_idx || got_idx == ast.byteptr_type_idx
|
||||||
|
|| (got_idx == ast.byte_type_idx && got.is_ptr()) {
|
||||||
|
if expected.is_ptr() || expected.is_pointer() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expected == ast.charptr_type && got == ast.char_type.ref() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if expected.has_flag(.optional) {
|
||||||
|
sym := c.table.get_type_symbol(got)
|
||||||
|
if (sym.kind == .interface_ && sym.name == 'IError')
|
||||||
|
|| got in [ast.none_type, ast.error_type] {
|
||||||
|
return true
|
||||||
|
} else if !c.check_basic(got, expected.clear_flag(.optional)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !c.check_basic(got, expected) { // TODO: this should go away...
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if got.is_number() && expected.is_number() {
|
||||||
|
if got == ast.rune_type && expected == ast.byte_type {
|
||||||
|
return true
|
||||||
|
} else if expected == ast.rune_type && got == ast.byte_type {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c.promote_num(expected, got) != expected {
|
||||||
|
// println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expected.has_flag(.generic) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ? {
|
pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ? {
|
||||||
if got == 0 {
|
if got == 0 {
|
||||||
return error('unexpected 0 type')
|
return error('unexpected 0 type')
|
||||||
|
@ -190,7 +258,7 @@ fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type ast.Type, right
|
||||||
c.error('invalid operation: shift on type `$left_sym.name`', node.left.position())
|
c.error('invalid operation: shift on type `$left_sym.name`', node.left.position())
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if !right_type.is_int() {
|
if !right_type.is_int() && !c.pref.translated {
|
||||||
left_sym := c.table.get_type_symbol(left_type)
|
left_sym := c.table.get_type_symbol(left_type)
|
||||||
right_sym := c.table.get_type_symbol(right_type)
|
right_sym := c.table.get_type_symbol(right_type)
|
||||||
c.error('cannot shift non-integer type `$right_sym.name` into type `$left_sym.name`',
|
c.error('cannot shift non-integer type `$right_sym.name` into type `$left_sym.name`',
|
||||||
|
@ -260,7 +328,7 @@ fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type ast.Type, right
|
||||||
ast.u64_type { 63 }
|
ast.u64_type { 63 }
|
||||||
else { 64 }
|
else { 64 }
|
||||||
}
|
}
|
||||||
if ival > moffset {
|
if ival > moffset && !c.pref.translated {
|
||||||
c.error('shift count for type `$left_sym_final.name` too large (maximum: $moffset bits)',
|
c.error('shift count for type `$left_sym_final.name` too large (maximum: $moffset bits)',
|
||||||
node.right.position())
|
node.right.position())
|
||||||
return left_type
|
return left_type
|
||||||
|
@ -354,74 +422,6 @@ fn (c &Checker) promote_num(left_type ast.Type, right_type ast.Type) ast.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
|
|
||||||
pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
|
||||||
if got == expected {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
got_is_ptr := got.is_ptr()
|
|
||||||
exp_is_ptr := expected.is_ptr()
|
|
||||||
if got_is_ptr && exp_is_ptr {
|
|
||||||
if got.nr_muls() != expected.nr_muls() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exp_idx := expected.idx()
|
|
||||||
got_idx := got.idx()
|
|
||||||
if exp_idx == got_idx {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if exp_idx == ast.voidptr_type_idx || exp_idx == ast.byteptr_type_idx
|
|
||||||
|| (expected.is_ptr() && expected.deref().idx() == ast.byte_type_idx) {
|
|
||||||
if got.is_ptr() || got.is_pointer() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// allow direct int-literal assignment for pointers for now
|
|
||||||
// maybe in the future optionals should be used for that
|
|
||||||
if expected.is_real_pointer() {
|
|
||||||
if got == ast.int_literal_type {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if got_idx == ast.voidptr_type_idx || got_idx == ast.byteptr_type_idx
|
|
||||||
|| (got_idx == ast.byte_type_idx && got.is_ptr()) {
|
|
||||||
if expected.is_ptr() || expected.is_pointer() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if expected == ast.charptr_type && got == ast.char_type.ref() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if expected.has_flag(.optional) {
|
|
||||||
sym := c.table.get_type_symbol(got)
|
|
||||||
if (sym.kind == .interface_ && sym.name == 'IError')
|
|
||||||
|| got in [ast.none_type, ast.error_type] {
|
|
||||||
return true
|
|
||||||
} else if !c.check_basic(got, expected.clear_flag(.optional)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !c.check_basic(got, expected) { // TODO: this should go away...
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if got.is_number() && expected.is_number() {
|
|
||||||
if got == ast.rune_type && expected == ast.byte_type {
|
|
||||||
return true
|
|
||||||
} else if expected == ast.rune_type && got == ast.byte_type {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if c.promote_num(expected, got) != expected {
|
|
||||||
// println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if expected.has_flag(.generic) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut c Checker) check_expected(got ast.Type, expected ast.Type) ? {
|
pub fn (mut c Checker) check_expected(got ast.Type, expected ast.Type) ? {
|
||||||
if !c.check_types(got, expected) {
|
if !c.check_types(got, expected) {
|
||||||
return error(c.expected_msg(got, expected))
|
return error(c.expected_msg(got, expected))
|
||||||
|
|
|
@ -7463,7 +7463,7 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
|
||||||
if right_type.is_ptr() {
|
if right_type.is_ptr() {
|
||||||
return right_type.deref()
|
return right_type.deref()
|
||||||
}
|
}
|
||||||
if !right_type.is_pointer() {
|
if !right_type.is_pointer() && !c.pref.translated {
|
||||||
s := c.table.type_to_str(right_type)
|
s := c.table.type_to_str(right_type)
|
||||||
c.error('invalid indirect of `$s`', node.pos)
|
c.error('invalid indirect of `$s`', node.pos)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue