cgen: multi return structs + other fixes

pull/3937/head
Alexander Medvednikov 2020-03-04 20:17:29 +01:00
parent cd8a5d1f2e
commit 136aa763a3
2 changed files with 52 additions and 9 deletions

View File

@ -36,14 +36,25 @@ pub fn new_builder(pref &pref.Preferences) Builder {
}
pub fn (b mut Builder) gen_c(v_files []string) string {
t0 := time.ticks()
b.parsed_files = parser.parse_files(v_files, b.table)
b.parse_imports()
t1 := time.ticks()
parse_time := t1 - t0
println('PARSE: ${parse_time}ms')
//
b.checker.check_files(b.parsed_files)
t2 := time.ticks()
check_time := t2 - t1
println('CHECK: ${check_time}ms')
if b.checker.nr_errors > 0 {
exit(1)
}
// println('starting cgen...')
res := gen.cgen(b.parsed_files, b.table)
t3 := time.ticks()
gen_time := t3 - t2
println('C GEN: ${gen_time}ms')
println('cgen done')
// println(res)
return res

View File

@ -38,6 +38,28 @@ pub fn (g mut Gen) init() {
g.definitions.writeln('#include <inttypes.h>') // int64_t etc
g.definitions.writeln(c_builtin_types)
g.definitions.writeln(c_headers)
// Multi return structs
// TODO move to a method
g.definitions.writeln('// multi return structs')
for typ in g.table.types {
// sym := g.table.get_type_symbol(typ)
if typ.kind != .multi_return {
continue
}
name := typ.name.replace('.', '__')
info := typ.info as table.MultiReturn
g.definitions.writeln('typedef struct {')
// TODO copy pasta StructDecl
// for field in struct_info.fields {
for i, mr_typ in info.types {
field_type_sym := g.table.get_type_symbol(mr_typ)
type_name := field_type_sym.name.replace('.', '__')
g.definitions.writeln('\t$type_name arg_${i+1};')
}
g.definitions.writeln('} $name;\n')
// g.typedefs.writeln('typedef struct $name $name;')
}
g.definitions.writeln('// end of definitions #endif')
}
pub fn (g &Gen) save() {}
@ -136,7 +158,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
}
}
ast.FnDecl {
if it.is_c {
if it.is_c || it.name == 'malloc' {
return
}
g.reset_tmp_count()
@ -147,21 +169,31 @@ fn (g mut Gen) stmt(node ast.Stmt) {
}
else {
type_sym := g.table.get_type_symbol(it.typ)
mut name := it.name.replace('.', '__')
mut name := it.name
if it.is_method {
name = g.table.get_type_symbol(it.receiver.typ).name + '_' + name
}
g.write('$type_sym.name ${name}(')
g.definitions.write('$type_sym.name ${name}(')
name = name.replace('.', '__')
// type_name := g.table.type_to_str(it.typ)
type_name := type_sym.name.replace('.', '__') // g.table.type_to_str(it.typ)
g.write('$type_name ${name}(')
g.definitions.write('$type_name ${name}(')
}
no_names := it.args.len > 0 && it.args[0].name == 'arg_1'
for i, arg in it.args {
arg_type_sym := g.table.get_type_symbol(arg.typ)
mut arg_type_name := arg_type_sym.name
mut arg_type_name := arg_type_sym.name.replace('.', '__')
if i == it.args.len - 1 && it.is_variadic {
arg_type_name = 'variadic_$arg_type_sym.name'
}
if no_names {
g.write(arg_type_name)
g.definitions.write(arg_type_name)
}
else {
g.write(arg_type_name + ' ' + arg.name)
g.definitions.write(arg_type_name + ' ' + arg.name)
}
if i < it.args.len - 1 {
g.write(', ')
g.definitions.write(', ')
@ -239,13 +271,13 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.writeln(';')
}
ast.StructDecl {
name := it.name.replace('.', '__')
g.writeln('typedef struct {')
for field in it.fields {
field_type_sym := g.table.get_type_symbol(field.typ)
g.writeln('\t$field_type_sym.name $field.name;')
}
g.writeln('} $it.name;')
name := it.name.replace('.', '__')
g.writeln('} $name;')
g.typedefs.writeln('typedef struct $name $name;')
}
ast.TypeDecl {