parser/cgen: interface <<; `any` type
parent
2a016d03ac
commit
de749e9d3b
|
@ -391,7 +391,7 @@ pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
// `array << elm`
|
// `array << elm`
|
||||||
c.fail_if_immutable(infix_expr.left)
|
c.fail_if_immutable(infix_expr.left)
|
||||||
// the expressions have different types (array_x and x)
|
// the expressions have different types (array_x and x)
|
||||||
if c.table.check(c.table.value_type(left_type), right_type) {
|
if c.table.check(right_type, c.table.value_type(left_type)) { // , right_type) {
|
||||||
// []T << T
|
// []T << T
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
s := left.name.replace('array_', '[]')
|
s := left.name.replace('array_', '[]')
|
||||||
c.error('cannot append `$right.name` to `$s', infix_expr.right.position())
|
c.error('cannot append `$right.name` to `$s`', infix_expr.right.position())
|
||||||
return table.void_type
|
return table.void_type
|
||||||
} else if !left.is_int() {
|
} else if !left.is_int() {
|
||||||
c.error('cannot shift type $right.name into non-integer type $left.name', infix_expr.left.position())
|
c.error('cannot shift type $right.name into non-integer type $left.name', infix_expr.left.position())
|
||||||
|
|
|
@ -1470,7 +1470,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.write('array_push(&')
|
g.write('array_push(&')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(', &($elem_type_str[]){ ')
|
g.write(', &($elem_type_str[]){ ')
|
||||||
|
elem_sym := g.table.get_type_symbol(info.elem_type)
|
||||||
|
if elem_sym.kind == .interface_ {
|
||||||
|
g.interface_call(node.right_type, info.elem_type)
|
||||||
|
}
|
||||||
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
||||||
|
if elem_sym.kind == .interface_ {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
}
|
}
|
||||||
} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in
|
} else if (node.left_type == node.right_type) && node.left_type.is_float() && node.op in
|
||||||
|
|
|
@ -176,6 +176,7 @@ pub const (
|
||||||
ustring_type_idx = 19
|
ustring_type_idx = 19
|
||||||
array_type_idx = 20
|
array_type_idx = 20
|
||||||
map_type_idx = 21
|
map_type_idx = 21
|
||||||
|
any_type_idx = 22
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
|
@ -220,6 +221,7 @@ pub const (
|
||||||
ustring_type = new_type(ustring_type_idx)
|
ustring_type = new_type(ustring_type_idx)
|
||||||
array_type = new_type(array_type_idx)
|
array_type = new_type(array_type_idx)
|
||||||
map_type = new_type(map_type_idx)
|
map_type = new_type(map_type_idx)
|
||||||
|
any_type = new_type(any_type_idx)
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
|
@ -227,7 +229,7 @@ pub const (
|
||||||
'u16',
|
'u16',
|
||||||
'u32',
|
'u32',
|
||||||
'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
|
'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
|
||||||
'map', 'struct',
|
'map', 'any', 'struct',
|
||||||
'mapnode', 'size_t']
|
'mapnode', 'size_t']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -270,6 +272,7 @@ pub enum Kind {
|
||||||
array
|
array
|
||||||
array_fixed
|
array_fixed
|
||||||
map
|
map
|
||||||
|
any
|
||||||
struct_
|
struct_
|
||||||
multi_return
|
multi_return
|
||||||
sum_type
|
sum_type
|
||||||
|
@ -427,6 +430,10 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
kind: .map
|
kind: .map
|
||||||
name: 'map'
|
name: 'map'
|
||||||
})
|
})
|
||||||
|
t.register_type_symbol(TypeSymbol{
|
||||||
|
kind: .any
|
||||||
|
name: 'any'
|
||||||
|
})
|
||||||
t.register_type_symbol(TypeSymbol{
|
t.register_type_symbol(TypeSymbol{
|
||||||
kind: .size_t
|
kind: .size_t
|
||||||
name: 'size_t'
|
name: 'size_t'
|
||||||
|
@ -466,6 +473,7 @@ pub fn (t &TypeSymbol) is_number() bool {
|
||||||
return t.is_int() || t.is_float()
|
return t.is_int() || t.is_float()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for debugging/errors only, perf is not an issue
|
||||||
pub fn (k Kind) str() string {
|
pub fn (k Kind) str() string {
|
||||||
k_str := match k {
|
k_str := match k {
|
||||||
.placeholder { 'placeholder' }
|
.placeholder { 'placeholder' }
|
||||||
|
@ -496,6 +504,7 @@ pub fn (k Kind) str() string {
|
||||||
.sum_type { 'sum_type' }
|
.sum_type { 'sum_type' }
|
||||||
.alias { 'alias' }
|
.alias { 'alias' }
|
||||||
.enum_ { 'enum' }
|
.enum_ { 'enum' }
|
||||||
|
.any { 'any' }
|
||||||
else { 'unknown' }
|
else { 'unknown' }
|
||||||
}
|
}
|
||||||
return k_str
|
return k_str
|
||||||
|
@ -535,7 +544,7 @@ pub:
|
||||||
foo string
|
foo string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: FExpr here is a actually an ast.Expr .
|
// NB: FExpr here is a actually an ast.Expr .
|
||||||
// It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe()
|
// It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe()
|
||||||
// That hack is needed to break an import cycle between v.ast and v.table .
|
// That hack is needed to break an import cycle between v.ast and v.table .
|
||||||
type FExpr = voidptr | byteptr
|
type FExpr = voidptr | byteptr
|
||||||
|
|
|
@ -469,6 +469,9 @@ pub fn (t &Table) check(got, expected Type) bool {
|
||||||
if exp_idx == voidptr_type_idx || got_idx == voidptr_type_idx {
|
if exp_idx == voidptr_type_idx || got_idx == voidptr_type_idx {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if exp_idx == any_type_idx || got_idx == any_type_idx {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if (exp_idx in pointer_type_idxs || exp_idx in number_type_idxs) && (got_idx in pointer_type_idxs ||
|
if (exp_idx in pointer_type_idxs || exp_idx in number_type_idxs) && (got_idx in pointer_type_idxs ||
|
||||||
got_idx in number_type_idxs) {
|
got_idx in number_type_idxs) {
|
||||||
return true
|
return true
|
||||||
|
@ -485,7 +488,7 @@ pub fn (t &Table) check(got, expected Type) bool {
|
||||||
// # NOTE: use symbols from this point on for perf
|
// # NOTE: use symbols from this point on for perf
|
||||||
got_type_sym := t.get_type_symbol(got)
|
got_type_sym := t.get_type_symbol(got)
|
||||||
exp_type_sym := t.get_type_symbol(expected)
|
exp_type_sym := t.get_type_symbol(expected)
|
||||||
//
|
// Handle expected interface
|
||||||
if exp_type_sym.kind == .interface_ {
|
if exp_type_sym.kind == .interface_ {
|
||||||
mut info := exp_type_sym.info as Interface
|
mut info := exp_type_sym.info as Interface
|
||||||
// println('gen_types before')
|
// println('gen_types before')
|
||||||
|
@ -498,6 +501,13 @@ pub fn (t &Table) check(got, expected Type) bool {
|
||||||
// println(info.gen_types)
|
// println(info.gen_types)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// Handle expected interface array
|
||||||
|
/*
|
||||||
|
if exp_type_sym.kind == .array && t.get_type_symbol(t.value_type(exp_idx)).kind == .interface_ {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//
|
||||||
if exp_type_sym.kind == .function && got_type_sym.kind == .int {
|
if exp_type_sym.kind == .function && got_type_sym.kind == .int {
|
||||||
// TODO temporary
|
// TODO temporary
|
||||||
// fn == 0
|
// fn == 0
|
||||||
|
|
|
@ -91,3 +91,11 @@ interface Speaker {
|
||||||
speak()
|
speak()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn test_interface_array() {
|
||||||
|
mut animals := []Speaker{}
|
||||||
|
animals = [ Cat{}, Dog{} ]
|
||||||
|
animals << Cat{}
|
||||||
|
assert true
|
||||||
|
assert animals.len == 3
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue