all: interface arrays
parent
3d8853af2b
commit
2fc05b814c
|
@ -634,18 +634,21 @@ pub:
|
|||
|
||||
pub struct ArrayInit {
|
||||
pub:
|
||||
pos token.Position
|
||||
exprs []Expr
|
||||
is_fixed bool
|
||||
has_val bool
|
||||
mod string
|
||||
len_expr Expr
|
||||
has_len bool
|
||||
has_cap bool
|
||||
cap_expr Expr
|
||||
pos token.Position
|
||||
exprs []Expr
|
||||
is_fixed bool
|
||||
has_val bool
|
||||
mod string
|
||||
len_expr Expr
|
||||
has_len bool
|
||||
has_cap bool
|
||||
cap_expr Expr
|
||||
mut:
|
||||
elem_type table.Type
|
||||
typ table.Type
|
||||
is_interface bool // array of interfaces e.g. `[]Animal` `[Dog{}, Cat{}]`
|
||||
interface_types []table.Type // [Dog, Cat]
|
||||
interface_type table.Type // Animal
|
||||
elem_type table.Type
|
||||
typ table.Type
|
||||
}
|
||||
|
||||
pub struct MapInit {
|
||||
|
|
|
@ -211,7 +211,7 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
|
|||
c.error('struct name must begin with capital letter', pos)
|
||||
}
|
||||
for i, field in decl.fields {
|
||||
for j in 0..i {
|
||||
for j in 0 .. i {
|
||||
if field.name == decl.fields[j].name {
|
||||
c.error('field name `$field.name` duplicate', field.pos)
|
||||
}
|
||||
|
@ -367,9 +367,8 @@ pub fn (mut c Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
|||
return table.bool_type
|
||||
}
|
||||
.plus, .minus, .mul, .div {
|
||||
if infix_expr.op == .div &&
|
||||
(infix_expr.right is ast.IntegerLiteral && infix_expr.right.str() == '0' ||
|
||||
infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0) {
|
||||
if infix_expr.op == .div && (infix_expr.right is ast.IntegerLiteral && infix_expr.right.str() ==
|
||||
'0' || infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0) {
|
||||
c.error('division by zero', infix_expr.right.position())
|
||||
}
|
||||
if left.kind in [.array, .array_fixed, .map, .struct_] && !left.has_method(infix_expr.op.str()) {
|
||||
|
@ -743,7 +742,8 @@ pub fn (mut c Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
|||
if !found_in_args && call_expr.mod in ['builtin', 'main'] {
|
||||
scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||
if _ := scope.find_var(fn_name) {
|
||||
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`', call_expr.pos)
|
||||
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`',
|
||||
call_expr.pos)
|
||||
}
|
||||
}
|
||||
call_expr.return_type = f.return_type
|
||||
|
@ -1117,27 +1117,49 @@ pub fn (mut c Checker) array_init(array_init mut ast.ArrayInit) table.Type {
|
|||
}
|
||||
// [1,2,3]
|
||||
if array_init.exprs.len > 0 && array_init.elem_type == table.void_type {
|
||||
expecting_interface_array := c.expected_type != 0 && c.table.get_type_symbol(c.table.value_type(c.expected_type)).kind ==
|
||||
.interface_
|
||||
mut expected_value_type := table.void_type
|
||||
mut expecting_interface_array := false
|
||||
cap := array_init.exprs.len
|
||||
mut interface_types := []table.Type{cap: cap}
|
||||
if c.expected_type != 0 {
|
||||
expected_value_type = c.table.value_type(c.expected_type)
|
||||
if c.table.get_type_symbol(expected_value_type).kind == .interface_ {
|
||||
// Array of interfaces? (`[dog, cat]`) Save the interface type (`Animal`)
|
||||
expecting_interface_array = true
|
||||
array_init.interface_type = expected_value_type
|
||||
array_init.is_interface = true
|
||||
}
|
||||
}
|
||||
// expecting_interface_array := c.expected_type != 0 &&
|
||||
// c.table.get_type_symbol(c.table.value_type(c.expected_type)).kind == .interface_
|
||||
//
|
||||
// if expecting_interface_array {
|
||||
// println('ex $c.expected_type')
|
||||
// }
|
||||
for i, expr in array_init.exprs {
|
||||
typ := c.expr(expr)
|
||||
if expecting_interface_array {
|
||||
if i == 0 {
|
||||
elem_type = expected_value_type
|
||||
c.expected_type = elem_type
|
||||
}
|
||||
interface_types << typ
|
||||
continue
|
||||
}
|
||||
// The first element's type
|
||||
if i == 0 {
|
||||
elem_type = typ
|
||||
c.expected_type = typ
|
||||
continue
|
||||
}
|
||||
if expecting_interface_array {
|
||||
continue
|
||||
}
|
||||
if !c.table.check(elem_type, typ) {
|
||||
elem_type_sym := c.table.get_type_symbol(elem_type)
|
||||
c.error('expected array element with type `$elem_type_sym.name`', array_init.pos)
|
||||
}
|
||||
}
|
||||
if expecting_interface_array {
|
||||
array_init.interface_types = interface_types
|
||||
}
|
||||
if array_init.is_fixed {
|
||||
idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len, 1)
|
||||
array_init.typ = table.new_type(idx)
|
||||
|
|
|
@ -996,7 +996,12 @@ fn (mut f Fmt) array_init(it ast.ArrayInit) {
|
|||
if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type {
|
||||
// `x := []string`
|
||||
f.write(f.type_to_str(it.typ))
|
||||
f.write('{}')
|
||||
f.write('{')
|
||||
if it.has_cap {
|
||||
f.write('cap: ')
|
||||
f.expr(it.cap_expr)
|
||||
}
|
||||
f.write('}')
|
||||
return
|
||||
}
|
||||
// `[1,2,3]`
|
||||
|
|
|
@ -87,8 +87,8 @@ mut:
|
|||
array_fn_definitions []string // array equality functions that have been defined
|
||||
is_json_fn bool // inside json.encode()
|
||||
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
||||
attr string
|
||||
is_builtin_mod bool
|
||||
attr string
|
||||
is_builtin_mod bool
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -450,7 +450,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
ast.Attr {
|
||||
g.attr = it.name
|
||||
if it.name == 'inline' {
|
||||
//g.writeln(it.name)
|
||||
// g.writeln(it.name)
|
||||
} else {
|
||||
g.writeln('//[$it.name]')
|
||||
}
|
||||
|
@ -517,14 +517,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
ast.FnDecl {
|
||||
mut skip := false
|
||||
pos := g.out.buf.len
|
||||
if g.pref.build_mode==.build_module {
|
||||
if !it.name.starts_with(g.module_built + '.'){
|
||||
if g.pref.build_mode == .build_module {
|
||||
if !it.name.starts_with(g.module_built + '.') {
|
||||
// Skip functions that don't have to be generated
|
||||
// for this module.
|
||||
skip = true
|
||||
skip = true
|
||||
}
|
||||
if g.is_builtin_mod && g.module_built == 'builtin' {
|
||||
skip=false
|
||||
skip = false
|
||||
}
|
||||
if !skip {
|
||||
println('build module `$g.module_built` fn `$it.name`')
|
||||
|
@ -606,7 +606,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
g.definitions.writeln('} $it.name;')
|
||||
}
|
||||
ast.Module {
|
||||
g.is_builtin_mod = it.name=='builtin'
|
||||
g.is_builtin_mod = it.name == 'builtin'
|
||||
}
|
||||
ast.Return {
|
||||
g.write_defer_stmts_when_needed()
|
||||
|
@ -1176,7 +1176,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.write('.')
|
||||
}
|
||||
if it.expr_type == 0 {
|
||||
verror('cgen: SelectorExpr typ=0 field=$it.field')
|
||||
verror('cgen: SelectorExpr typ=0 field=$it.field $g.file.path $it.pos.line_nr')
|
||||
}
|
||||
g.write(c_name(it.field))
|
||||
}
|
||||
|
@ -3361,35 +3361,7 @@ ${interface_name} I_${cctype}_to_${interface_name}(${cctype} x) {
|
|||
|
||||
fn (mut g Gen) array_init(it ast.ArrayInit) {
|
||||
type_sym := g.table.get_type_symbol(it.typ)
|
||||
if type_sym.kind != .array_fixed {
|
||||
// elem_sym := g.table.get_type_symbol(it.elem_type)
|
||||
elem_type_str := g.typ(it.elem_type)
|
||||
if it.exprs.len == 0 {
|
||||
g.write('__new_array(')
|
||||
if it.has_len {
|
||||
g.expr(it.len_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
if it.has_cap {
|
||||
g.expr(it.cap_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
g.write('sizeof($elem_type_str))')
|
||||
} else {
|
||||
len := it.exprs.len
|
||||
g.write('new_array_from_c_array($len, $len, sizeof($elem_type_str), ')
|
||||
g.write('($elem_type_str[$len]){\n\t\t')
|
||||
for expr in it.exprs {
|
||||
g.expr(expr)
|
||||
g.write(', ')
|
||||
}
|
||||
g.write('\n})')
|
||||
}
|
||||
} else {
|
||||
if type_sym.kind == .array_fixed {
|
||||
g.write('{')
|
||||
for i, expr in it.exprs {
|
||||
g.expr(expr)
|
||||
|
@ -3398,5 +3370,41 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
|
|||
}
|
||||
}
|
||||
g.write('}')
|
||||
return
|
||||
}
|
||||
// elem_sym := g.table.get_type_symbol(it.elem_type)
|
||||
elem_type_str := g.typ(it.elem_type)
|
||||
if it.exprs.len == 0 {
|
||||
g.write('__new_array(')
|
||||
if it.has_len {
|
||||
g.expr(it.len_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
if it.has_cap {
|
||||
g.expr(it.cap_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
g.write('sizeof($elem_type_str))')
|
||||
return
|
||||
}
|
||||
len := it.exprs.len
|
||||
g.write('new_array_from_c_array($len, $len, sizeof($elem_type_str), ')
|
||||
g.write('($elem_type_str[$len]){\n\t\t')
|
||||
for i, expr in it.exprs {
|
||||
if it.is_interface {
|
||||
sym := g.table.get_type_symbol(it.interface_types[i])
|
||||
isym := g.table.get_type_symbol(it.interface_type)
|
||||
g.write('I_${sym.name}_to_${isym.name}(')
|
||||
}
|
||||
g.expr(expr)
|
||||
if it.is_interface {
|
||||
g.write(')')
|
||||
}
|
||||
g.write(', ')
|
||||
}
|
||||
g.write('\n})')
|
||||
}
|
||||
|
|
|
@ -201,9 +201,9 @@ pub fn (mut p Parser) close_scope() {
|
|||
ast.Var {
|
||||
if !it.is_used && !it.name.starts_with('__') {
|
||||
if p.pref.is_prod {
|
||||
p.error_with_pos('Unused variable: $it.name', it.pos)
|
||||
p.error_with_pos('unused variable: `$it.name`', it.pos)
|
||||
} else {
|
||||
p.warn_with_pos('Unused variable: $it.name', it.pos)
|
||||
p.warn_with_pos('unused variable: `$it.name`', it.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1249,7 +1249,6 @@ fn (mut p Parser) assoc() ast.Assoc {
|
|||
fields: fields
|
||||
exprs: vals
|
||||
pos: pos
|
||||
// typ: v.typ
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
|||
return &t.types[idx]
|
||||
}
|
||||
// this should never happen
|
||||
panic('get_type_symbol: invalid type (typ=$typ idx=${idx}). This should never happen')
|
||||
panic('get_type_symbol: invalid type (typ=$typ idx=${idx}). Compiler bug. This should never happen')
|
||||
}
|
||||
|
||||
[inline]
|
||||
|
|
|
@ -46,7 +46,7 @@ fn test_perform_speak() {
|
|||
perform_speak(dog)
|
||||
cat := Cat{}
|
||||
perform_speak(cat)
|
||||
//perform_speakers([dog, cat])
|
||||
perform_speakers([dog, cat])
|
||||
/*
|
||||
f := Foo {
|
||||
speaker: dog
|
||||
|
@ -62,6 +62,7 @@ interface Speak2er {
|
|||
speak()
|
||||
}
|
||||
|
||||
|
||||
struct Foo {
|
||||
speaker Speaker
|
||||
speakers []Speaker
|
||||
|
|
Loading…
Reference in New Issue