cgen: fix fixed array consts and pointer interfaces

pull/4682/head
Alexander Medvednikov 2020-05-02 15:18:49 +02:00
parent a9a8539e41
commit 44c00199b6
2 changed files with 27 additions and 12 deletions

View File

@ -1995,6 +1995,14 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
ast.IntegerLiteral {
g.const_decl_simple_define(name, val)
}
ast.ArrayInit {
if it.is_fixed {
styp := g.typ(it.typ)
g.definitions.writeln('$styp _const_$name = $val; // fixed array const')
} else {
g.const_decl_init_later(name, val, field.typ)
}
}
ast.StringLiteral {
g.definitions.writeln('string _const_$name; // a string literal, inited later')
if g.pref.build_mode != .build_module {
@ -2002,11 +2010,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
}
}
else {
// Initialize more complex consts in `void _vinit(){}`
// (C doesn't allow init expressions that can't be resolved at compile time).
styp := g.typ(field.typ)
g.definitions.writeln('$styp _const_$name; // inited later')
g.inits.writeln('\t_const_$name = $val;')
g.const_decl_init_later(name, val, field.typ)
}
}
}
@ -2021,6 +2025,14 @@ fn (mut g Gen) const_decl_simple_define(name, val string) {
g.definitions.writeln(val)
}
fn (mut g Gen) const_decl_init_later(name, val string, typ table.Type) {
// Initialize more complex consts in `void _vinit(){}`
// (C doesn't allow init expressions that can't be resolved at compile time).
styp := g.typ(typ)
g.definitions.writeln('$styp _const_$name; // inited later')
g.inits.writeln('\t_const_$name = $val;')
}
fn (mut g Gen) struct_init(struct_init ast.StructInit) {
mut info := &table.Struct{}
mut is_struct := false
@ -2172,7 +2184,6 @@ fn (mut g Gen) write_init_function() {
}
}
const (
builtins = ['string', 'array', 'KeyValue', 'DenseArray', 'map', 'Option']
)
@ -2377,7 +2388,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
// only floats should have precision specifier
if fields.len > 2 || fields.len == 2 && !(node.expr_types[i].is_float()) || node.expr_types[i].is_signed() &&
!(fspec in [`d`, `c`, `x`, `X`, `o`]) || node.expr_types[i].is_unsigned() && !(fspec in [`u`,
`x`, `X`, `o`, `c`]) || node.expr_types[i].is_float() && !(fspec in [`E`, `F`, `G`, `e`, `f`,
`x`, `X`, `o`, `c`]) || node.expr_types[i].is_float() && !(fspec in [`E`, `F`, `G`,
`e`, `f`,
`g`, `e`]) {
verror('illegal format specifier ${fspec:c} for type ${g.table.get_type_name(node.expr_types[i])}')
}
@ -3374,9 +3386,9 @@ fn (v &Gen) interface_table() string {
// Speaker_Cat_index = 0
interface_index_name := '_${interface_name}_${ptr_ctype}_index'
generated_casting_functions += '
${interface_name} I_${cctype}_to_${interface_name}(${cctype} x) {
${interface_name} I_${cctype}_to_${interface_name}(${cctype}* x) {
return (${interface_name}){
._object = (void*) memdup(&x, sizeof(${cctype})),
._object = (void*) memdup(x, sizeof(${cctype})),
._interface_idx = ${interface_index_name} };
}
'
@ -3470,4 +3482,7 @@ fn (g &Gen) interface_call(typ, interface_type table.Type) {
interface_styp := g.typ(interface_type).replace('*', '')
styp := g.typ(typ).replace('*', '')
g.write('I_${styp}_to_${interface_styp}(')
if !typ.is_ptr() {
g.write('&')
}
}

View File

@ -559,12 +559,12 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
arg_is_ptr := expected_type.is_ptr() || expected_type.idx() in table.pointer_type_idxs
expr_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in table.pointer_type_idxs
exp_sym := g.table.get_type_symbol(expected_type)
if arg.is_mut && !arg_is_ptr {
g.write('&/*mut*/')
} else if arg_is_ptr && !expr_is_ptr {
if arg.is_mut {
sym := g.table.get_type_symbol(expected_type)
if sym.kind == .array {
if exp_sym.kind == .array {
// Special case for mutable arrays. We can't `&` function
// results, have to use `(array[]){ expr }[0]` hack.
g.write('&/*111*/(array[]){')
@ -576,7 +576,7 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
if !g.is_json_fn {
g.write('&/*qq*/')
}
} else if !arg_is_ptr && expr_is_ptr {
} else if !arg_is_ptr && expr_is_ptr && exp_sym.kind != .interface_ {
// Dereference a pointer if a value is required
g.write('*/*d*/')
}